स्ट्रिंग लिखते समय मुझे एक विभाजन दोष क्यों मिलता है?
C99 N1256 ड्राफ्ट
चरित्र स्ट्रिंग शाब्दिक के दो अलग-अलग उपयोग हैं:
प्रारंभिक char[]
:
char c[] = "abc";
यह "अधिक जादू" है, और 6.7.8 / 14 "प्रारंभिककरण" में वर्णित है:
वर्ण प्रकार का एक वर्ण वर्ण स्ट्रिंग शाब्दिक द्वारा प्रारंभ किया जा सकता है, वैकल्पिक रूप से ब्रेसिज़ में संलग्न है। चरित्र स्ट्रिंग शाब्दिक के क्रमिक वर्ण (यदि कमरे में या यदि सरणी अज्ञात आकार का है, तो समाप्ति वर्ण सहित), सरणी के तत्वों को इनिशियलाइज़ करता है।
तो यह सिर्फ एक शॉर्टकट है:
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 में, एक बाइट या मूल्य शून्य का कोड प्रत्येक मल्टीबीट चरित्र अनुक्रम में जोड़ा जाता है जो एक स्ट्रिंग शाब्दिक या शाब्दिक परिणाम होता है। मल्टीबाइट कैरेक्टर सीक्वेंस का इस्तेमाल तब स्टैटिक स्टोरेज की अवधि और लंबाई को व्यवस्थित करने के लिए किया जाता है। चरित्र स्ट्रिंग शाब्दिकों के लिए, सरणी तत्वों में चार वर्ण होते हैं, और इन्हें मल्टीबाइट वर्ण अनुक्रम के अलग-अलग बाइट्स के साथ आरंभ किया जाता है ...]
6 यह स्पष्ट नहीं है कि क्या ये सरणियाँ अलग-अलग हैं बशर्ते उनके तत्वों में उचित मूल्य हों। यदि प्रोग्राम ऐसे सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।
6.7.8 / 32 "प्रारंभिक" एक प्रत्यक्ष उदाहरण देता है:
उदाहरण 8: घोषणा
char s[] = "abc", t[3] = "abc";
"सादे" वर्ण सरणी वस्तुओं को परिभाषित करता है s
और t
जिनके तत्व वर्ण स्ट्रिंग शाब्दिक के साथ आरंभिक होते हैं।
यह घोषणा समान है
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
सरणियों की सामग्री परिवर्तनीय हैं। दूसरी ओर, घोषणा
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
निष्कर्ष: GCC 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