为什么这段代码没有给我分段错误? 我只分配了1个字符,但输入了1个以上的字符。
char **names;
names=malloc(2*sizeof(char *));
names[0]=malloc(sizeof(char)*1) ;
names[0]="ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC";
printf("%s",names[0]);
我希望它会产生细分错误。
答案 0 :(得分:6)
在您的代码中
names[0]=malloc(sizeof(char)*1) ;
names[0]="ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC";
您基本上是在覆盖变量names[0]
的值,即存储指向它的另一个指针(字符串文字的起始地址)。没有理由应该产生分段错误。但是,它将导致memory leak,因为您丢失了malloc()
返回的原始指针,并且将永远没有机会free()
。
OTOH,如果您会写类似的东西
names[0]=malloc(sizeof(char)*1) ;
strcpy(names[0], "ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC");
您试图访问超出分配范围的内存位置时,将调用undefined behavior。再者,细分错误是可能的众多副作用之一,它从未得到保证。
答案 1 :(得分:4)
您的代码格式正确,因此没有理由对其进行分段。让我们分解一下:
char **names;
这声明了一个指向char
的指针。
names=malloc(2*sizeof(char *));
这将为大小为2的char *
数组分配空间,并将该地址分配给names
。
names[0]=malloc(sizeof(char)*1) ;
这将为大小为1的char
数组分配空间,并将该地址分配给names[0]
。
names[0]="ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC";
在这里变得很有趣。这会将给定字符串常量的地址分配给names[0]
,覆盖将分配给上一行分配的内存的地址。这也会泄漏在前一行分配的内存。
printf("%s",names[0]);
这将打印names[0]
指向的字符串。因为它包含字符串文字"ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC"
的地址,所以它就是打印出来的内容。
您可能不想这样做,而不是为names[0]
分配字符串文字:
strcpy(names[0], "ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC");
这会将字符串文字的内容复制到names[0]
,后者仅指向分配的内存的1个字节。但是,此处无法保证存在段错误。
在分配的内存末尾进行写操作时,将调用undefined behavior,这意味着代码可能崩溃,输出奇怪的结果或看起来可以正常工作。仅仅因为代码可能崩溃并不意味着它会。
答案 2 :(得分:0)
如其他答案所指出的那样,将指向字符串文字中第一个字符的指针分配给names[0]
,而不是将字符串复制到分配的对象中。另外,如果将字符串文字分配给字符指针变量,则应将其声明为const
。
在C语言中工作时,程序员需要创建自己的安全网。下面是一个函数示例,如果要分配的字符串太长,该函数将终止程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof (ptr)[0])
static void Copy(const char source[], int sourceLen, char target[], int targetLen)
{
if (targetLen >= sourceLen) {
strcpy(target, source);
} else {
fprintf(stderr, "Copy failed\n");
exit(EXIT_FAILURE);
}
}
int main(void)
{
char source[] = "ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC";
char *target;
int targetLen = 1;
NEW_ARRAY(target, targetLen);
Copy(source, LEN(source), target, targetLen);
puts(target);
return 0;
}