简体   繁体   English

内存分配如何与 char 指针(字符串文字、数组)一起使用?

[英]How does memory allocation work with char pointers(string literals, arrays)?

Currently reading K&R and just got stumbled across the char pointers.目前正在阅读 K&R,只是偶然发现了 char 指针。 There's nothing about memory allocation when defining char pointers in the book rn, maybe it'll be explained later. rn书里定义char指针的时候并没有讲到内存分配,说不定后面会解释。 But it just doesn't make sense so I'm seeking help :)但这只是没有意义,所以我正在寻求帮助:)

1 1

// No errors
char *name;
char *altname;
strcpy(altname,name);

2 2

// No errors, internals of *name have been successfully moved to *altname
char *name = "HI";
char *altname;
strcpy(altname, name);

3 3

// Segmentation fault, regardless of how I define *altname
char *name = "HI";
char *altname = "randomstring";
strcpy(altname, name);

4 4

// Segmentation fault, regardless of how I define *altname
char *name;
char *altname = "     ";
strcpy(altname, name);

5 5

// copies internals of *name only if size of char s[] > 8???
char s[9];
char n[] = {'c', 'b'};
char *name = n;
char *altname = s;
strcpy(altname, name);

Why does the first example produce no error, even though there's no memory allocated?为什么第一个示例没有产生错误,即使没有分配内存?

Why does the second one successfully copy name to altname, even though there's no memory allocated for altname;为什么第二个成功地将 name 复制到 altname,即使没有为 altname 分配内存;

Why do the third and forth one core dump?为什么第三和第四个核心转储?

Why does the fifth one require size of s as >8?为什么第五个要求 s 的大小为 >8?

I'm a bit surprised that the first two examples worked.前两个例子奏效了,我有点惊讶。 strcpy takes the character array pointed to by the second argument and copies it to the character array pointed to by the first argument. strcpy将第二个参数指向的字符数组复制到第一个参数指向的字符数组中。

In your first example, the pointers name and altname aren't pointing to anything.在您的第一个示例中,指针namealtname没有指向任何东西。 They're uninitialized pointers.它们是未初始化的指针。 Now they have some value based on either whatever gunk was in memory when the main function was executed or just however the compiler decided to initialize them.现在,它们具有一些价值,这取决于执行main函数时内存中的任何垃圾,或者只是编译器决定初始化它们。 That's why I'm surprised that your code isn't crashing.这就是为什么我对您的代码没有崩溃感到惊讶的原因。

Anyway, the reason why your third example is segfaulting is you've set both pointers to point to string literals (ie, "HI" and "randomstring" ).无论如何,您的第三个示例是段错误的原因是您将两个指针都设置为指向字符串文字(即"HI""randomstring" )。 String literals are (most likely) stored in a read-only section of memory.字符串文字(很可能)存储在内存的只读部分中。 So, when you run strcpy with the destination pointer set to altname , you're trying to write to read-only memory.因此,当您在目标指针设置为altname的情况下运行strcpy时,您正在尝试写入只读内存。 That's an invalid use of memory and hence the crash.这是对内存的无效使用,因此会导致崩溃。 The same goes for your fourth example.你的第四个例子也是如此。

In the final example, your problem is that n is not null-terminated.在最后一个示例中,您的问题是n不是以空值结尾的。 strcpy keeps copying characters until it reaches a terminator (ie, '\0' ). strcpy不断复制字符,直到它到达终止符(即'\0' )。 You've put a 'c' and a 'b' in your array but no terminator.您在数组中放置了一个'c'和一个'b' ,但没有终止符。 Therefore, strcpy is going to keep copying even after it's reached the end of n .因此, strcpy将继续复制,即使它到达n的末尾。 The fact that it works when sizeof(s) is greater than 8 probably involves where a null byte happens to exist on your stack.它在sizeof(s)大于 8 时起作用的事实可能涉及您的堆栈上碰巧存在空字节的位置。 That is, if you make s too small, you'll write past the end of it and corrupt the memory on your stack.也就是说,如果你使s太小,你会写到它的末尾并破坏堆栈上的内存。 It's possible you're overriding your return pointer and thus returning to some invalid memory address when your function is done executing.您可能会覆盖您的返回指针,从而在您的函数执行完成时返回到一些无效的内存地址。

What you need to do is, instead of using pointers, use arrays.您需要做的是,使用数组而不是使用指针。 This will give you the storage space you need in a writable section of memory.这将在内存的可写部分中为您提供所需的存储空间。 You also need to make sure that your arrays are null-terminated.您还需要确保您的数组以空值结尾。 This can be done automatically by initializing your arrays with string literals.这可以通过使用字符串文字初始化数组来自动完成。

char name[] = "HI";
char altname[] = "randomstring";
strcpy(altname, name);
char s[3]; // Enough space to hold "cb" plus a null-terminator.
char n[] = "cb";
char *name = n;
char *altname = s;
strcpy(altname, name);

All code snippets are undefined behavior.所有代码片段都是未定义的行为。 There is no guarantee that you will get an error.无法保证您会收到错误。 As the term says, the behavior is undefined.正如术语所说,行为是未定义的。

In 1 and 2, one or both pointers are uninitialized and may point to memory that may or may not be protected against the programmed access, so you may or may not get an error or program crash.在 1 和 2 中,一个或两个指针未初始化,并且可能指向可能会或可能不会受到保护以防止编程访问的内存,因此您可能会或可能不会收到错误或程序崩溃。

In 3 and 4 you may get a reproducible segmentation fault because altname points to a string literal "randomstring" or " " which can be read-only, so you are not allowed to overwrite the memory where altname points to.在 3 和 4 中,您可能会遇到可重现的分段错误,因为altname指向可以只读的字符串文字"randomstring"" " ,因此不允许覆盖altname指向的内存。 In 4, name is uninitialized, so this might also be the cause of the segmentation fault. 4、 name未初始化,所以这也可能是segmentation fault的原因。

In 5, n is not a valid string that could be used for strcpy .在 5 中, n不是可用于strcpy的有效字符串。 The terminating '\0' is missing.缺少终止'\0' strcpy will (try to) copy everything after the end of n until it finds a '\0' . strcpy将(尝试)复制n结束后的所有内容,直到找到'\0' To fix it use要修复它,请使用

char n[] = {'c', 'b', '\0'};

or或者

char n[] = "cb";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM