স্ট্রিংয়ে লেখার সময় কেন আমি সেগমেন্টেশন ত্রুটি পেতে পারি?
C99 N1256 খসড়া
অক্ষর স্ট্রিং আক্ষরিক দুটি ভিন্ন ব্যবহার আছে:
আরম্ভ করুন char[]
:
char c[] = "abc";
এটি "আরও যাদু" এবং 6..7.৮ / ১৪ "ইনিশিয়ালাইজেশন" এ বর্ণিত:
অক্ষরের ধরণের একটি অ্যারে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে সংযুক্ত করা যেতে পারে। অক্ষরের স্ট্রিং আক্ষরিকের ধারাবাহিক অক্ষর (ঘর থাকলে অবিরাম আকারে টার্মিনেটিং নাল চরিত্র সহ) অ্যারের উপাদানগুলির সূচনা করে।
সুতরাং এটি কেবল একটি শর্টকাট:
char c[] = {'a', 'b', 'c', '\0'};
অন্য কোনও নিয়মিত অ্যারের মতো, c
পরিবর্তন করা যেতে পারে।
অন্য যে কোনও জায়গায়: এটি একটি উত্পন্ন করে:
সুতরাং আপনি যখন লিখুন:
char *c = "abc";
এটি এর অনুরূপ:
/* __unnamed is magic because modifying it gives UB. */
static char __unnamed[] = "abc";
char *c = __unnamed;
নোট থেকে অন্তর্নিহিত ঢালাই char[]
করার char *
, যা সবসময় বৈধ।
তারপরে আপনি যদি সংশোধন করেন c[0]
, __unnamed
আপনিও সংশোধন করুন , যা ইউবি।
এটি 6.4.5 "স্ট্রিং লিটারালস" এ নথিভুক্ত করা হয়েছে:
5 অনুবাদ পর্বে 7-এ, বাইট বা মান শূন্যের কোডটি প্রতিটি মাল্টবাইট চরিত্রের অনুক্রমের সাথে যুক্ত হয় যা স্ট্রিং আক্ষরিক বা আক্ষরিক থেকে ফলাফল results মাল্টিবাইট চরিত্রের সিক্যুয়েন্সটি তখন স্ট্যাটিক স্টোরেজ সময়কাল এবং সিক্যুয়েন্সটি পর্যাপ্ত রাখার জন্য যথেষ্ট দৈর্ঘ্যের একটি অ্যারে শুরু করার জন্য ব্যবহৃত হয়। চরিত্রের স্ট্রিং লিটারালগুলির জন্য, অ্যারের উপাদানগুলিতে টাইপ চর থাকে এবং মাল্টিবাইট অক্ষর ক্রমের পৃথক বাইটগুলির সাথে আরম্ভ করা হয় [...]
These এই অ্যারেগুলি পৃথক পৃথক কিনা এগুলি নির্ধারিত নয় যদি তাদের উপাদানগুলির উপযুক্ত মান থাকে। প্রোগ্রামটি যদি এমন অ্যারে সংশোধন করার চেষ্টা করে তবে আচরণটি সংজ্ঞায়িত।
Initial.7.৮ / ৩২ "ইনিশিয়ালাইজেশন" এর প্রত্যক্ষ উদাহরণ দেয়:
উদাহরণ 8: ঘোষণা
char s[] = "abc", t[3] = "abc";
"প্লেইন" চর অ্যারে অবজেক্টগুলি সংজ্ঞায়িত করে s
এবং t
যার উপাদানগুলি অক্ষর স্ট্রিং ল্যাটারাল দিয়ে শুরু করা হয়।
এই ঘোষণাটি সমান
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
অ্যারের সামগ্রীগুলি পরিবর্তনযোগ্য if অন্যদিকে, ঘোষণা
char *p = "abc";
p
"পয়েন্টার টু চর" টাইপ দিয়ে সংজ্ঞায়িত করে এবং এটি দৈর্ঘ্য 4 দিয়ে "চরের অ্যারে" টাইপযুক্ত কোনও অবজেক্টের দিকে নির্দেশ করতে ইনিশিয়াল করে যার উপাদানগুলি একটি অক্ষরের স্ট্রিং আক্ষরিক দিয়ে প্রাথমিক হয়। p
অ্যারের বিষয়বস্তুগুলি সংশোধন করার জন্য যদি চেষ্টা করা হয় , তবে আচরণটি সংজ্ঞায়িত।
জিসিসি 4.8 x86-64 ইএলএফ বাস্তবায়ন
কার্যক্রম:
#include <stdio.h>
int main(void) {
char *s = "abc";
printf("%s\n", s);
return 0;
}
সংকলন এবং পচনশীল:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
আউটপুট রয়েছে:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
উপসংহার: জিসিসি char*
এটিকে .rodata
বিভাগে রাখে, না .text
।
আমরা যদি এর জন্য একই করি char[]
:
char s[] = "abc";
আমরা প্রাপ্ত:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
সুতরাং এটি স্ট্যাকের মধ্যে (আপেক্ষিক %rbp
) সঞ্চিত হয় ।
তবে খেয়াল করুন যে ডিফল্ট লিঙ্কার স্ক্রিপ্টটি একই বিভাগে রাখে .rodata
এবং এতে .text
লেখার অনুমতি নেই। এটি দিয়ে পর্যবেক্ষণ করা যেতে পারে:
readelf -l a.out
যেটা বহন করে:
Section to Segment mapping:
Segment Sections...
02 .text .rodata