为什么此代码有效,但不会产生分段错误?

时间:2019-07-17 12:42:57

标签: c pointers malloc

为什么这段代码没有给我分段错误? 我只分配了1个字符,但输入了1个以上的字符。

char **names;

names=malloc(2*sizeof(char *));
names[0]=malloc(sizeof(char)*1) ;

names[0]="ATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATCCACTATCAHCTACHATC";

printf("%s",names[0]);

我希望它会产生细分错误。

3 个答案:

答案 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;
}