由strncpy()复制时预定义的字符串段错误

时间:2022-09-06 15:54:04

Why is it that ...

为什么......

char *dst = (char*) malloc(sizeof(char) * 11);
char *src = "ABCDEFGHIJKLMNOPQRSTUVQXYZ";
strncpy(dst, src, 10);

... works fine, but ...

......工作正常,但......

char *dst = "ABCDEFGHIJ\0";
char *src = "ABCDEFGHIJKLMNOPQRSTUVQXYZ\0";
strncpy(dst, src, 10);

... or even ...

... 甚至 ...

char *dst = "ABCDEFGHIJ\0";
char *src = "KLMNOPQRST\0";
strncpy(dst, src, 10);

gives segfault?

Also, how come this works:

另外,这是怎么回事:

char *dst = (char*) malloc(sizeof(char) * 10); // also works with 9
char *src = "ABCDEFGHIJKLMNOPQRSTUVQXYZ\0";
strncpy(dst, src, 10);

Copying 11 bytes into a pointer allocated with 10 bytes should in principle fail?

将11个字节复制到分配有10个字节的指针中原则上应该失败?

2 个解决方案

#1


The difference is that the string literals you initialized to the pointers dst and src in the later cases are stored in the data segment. A data segment is a portion of virtual address space of a program, which contains the global variables and static variables that are initialized by the programmer.

不同之处在于,在以后的情况下初始化为指针dst和src的字符串文字存储在数据段中。数据段是程序的虚拟地址空间的一部分,其包含由程序员初始化的全局变量和静态变量。

This segment can be further classified into initialized read-only area and initialized read-write area.

该段可以进一步分类为初始化的只读区域和初始化的读写区域。

For instance the global string defined by

例如,由...定义的全局字符串

char s[] = “hello world” 

in C and a C statement like int debug=1 outside the main (i.e. global) would be stored in initialized read-write area. And a global C statement like

在C和C语句之类的主调(即全局)之外的int debug = 1将存储在初始化的读写区域中。和全球C语句一样

const char* string = “hello world”

makes the string literal “hello world” to be stored in initialized read-only area and the character pointer variable string in initialized read-write area.

使字符串文字“hello world”存储在初始化的只读区域中,字符指针变量字符串存储在初始化的读写区域中。

And in the above case...

而在上述情况下......

char* dst = " ABCD........." ;

is equivalent to

相当于

const temp[]="ABCD......";

char* dst = &temp[0];

so the temp array which the dst is pointing will be stored in readonly memory and hence you cannot edit it...

所以dst指向的临时数组将存储在只读内存中,因此你无法编辑它...

Also in the final case even though you can copy 11 bytes into a pointer pointing to 10 bytes, you will encounter troubles during run time.... For eg: try freeing the pointer and you will face segmentation fault...( Undefined behaviour).

同样在最后的情况下,即使你可以将11个字节复制到指向10个字节的指针,你也会在运行时遇到麻烦....例如:尝试释放指针,你将面临分段错误...(未定义的行为)。

It is compiler dependent.

它取决于编译器。

#2


String literals may be stored in a read-only memory segment. You are not supposed to modify them.

字符串文字可以存储在只读存储器段中。你不应该修改它们。

Also, there's no checking for writing beyond bounds. Many of the security problems you hear of stem from the fact that there's a lot of code without any bounds checking.

此外,没有检查超出界限的写作。您听到的许多安全问题源于这样一个事实:有很多代码没有任何边界检查。

Writing beyond the bounds of allocated memory, as well as attempting to modify a string literal or other read-only/constant data, leads to undefined behavior.

写入超出已分配内存的范围,以及尝试修改字符串文字或其他只读/常量数据,会导致未定义的行为。

#1


The difference is that the string literals you initialized to the pointers dst and src in the later cases are stored in the data segment. A data segment is a portion of virtual address space of a program, which contains the global variables and static variables that are initialized by the programmer.

不同之处在于,在以后的情况下初始化为指针dst和src的字符串文字存储在数据段中。数据段是程序的虚拟地址空间的一部分,其包含由程序员初始化的全局变量和静态变量。

This segment can be further classified into initialized read-only area and initialized read-write area.

该段可以进一步分类为初始化的只读区域和初始化的读写区域。

For instance the global string defined by

例如,由...定义的全局字符串

char s[] = “hello world” 

in C and a C statement like int debug=1 outside the main (i.e. global) would be stored in initialized read-write area. And a global C statement like

在C和C语句之类的主调(即全局)之外的int debug = 1将存储在初始化的读写区域中。和全球C语句一样

const char* string = “hello world”

makes the string literal “hello world” to be stored in initialized read-only area and the character pointer variable string in initialized read-write area.

使字符串文字“hello world”存储在初始化的只读区域中,字符指针变量字符串存储在初始化的读写区域中。

And in the above case...

而在上述情况下......

char* dst = " ABCD........." ;

is equivalent to

相当于

const temp[]="ABCD......";

char* dst = &temp[0];

so the temp array which the dst is pointing will be stored in readonly memory and hence you cannot edit it...

所以dst指向的临时数组将存储在只读内存中,因此你无法编辑它...

Also in the final case even though you can copy 11 bytes into a pointer pointing to 10 bytes, you will encounter troubles during run time.... For eg: try freeing the pointer and you will face segmentation fault...( Undefined behaviour).

同样在最后的情况下,即使你可以将11个字节复制到指向10个字节的指针,你也会在运行时遇到麻烦....例如:尝试释放指针,你将面临分段错误...(未定义的行为)。

It is compiler dependent.

它取决于编译器。

#2


String literals may be stored in a read-only memory segment. You are not supposed to modify them.

字符串文字可以存储在只读存储器段中。你不应该修改它们。

Also, there's no checking for writing beyond bounds. Many of the security problems you hear of stem from the fact that there's a lot of code without any bounds checking.

此外,没有检查超出界限的写作。您听到的许多安全问题源于这样一个事实:有很多代码没有任何边界检查。

Writing beyond the bounds of allocated memory, as well as attempting to modify a string literal or other read-only/constant data, leads to undefined behavior.

写入超出已分配内存的范围,以及尝试修改字符串文字或其他只读/常量数据,会导致未定义的行为。