memset 字符串的 strcmp 上的 SIGSEGV

SIGSEV on strcmp of memset string

在下面的程序中,我希望 for 循环在 3 个元素后停止。 但它会无限期地继续下去,稍后会因核心转储而失败。

  1. malloc() needed forchar*[]`
  2. 如果我将内存设置为 0,strcmp 会失败吗?

.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
        char* str[10]; memset(str,0,10);

        str[0]=malloc(sizeof(char)*(strlen("Sample")+1));
        str[1]=malloc(sizeof(char)*(strlen("Sample")+1));
        str[2]=malloc(sizeof(char)*(strlen("Sample")+1));

        strcpy(str[0],"Sample");
        strcpy(str[1],"Sample");
        strcpy(str[2],"Sample");



        int i=0;
        for(i=0;strcmp("",str[i])!=0;i++)
        {
                printf("%d\n",i);;
        }
        return 0;
}

编辑: 即使使用 char* str[10]; memset(str,0,10*sizeof(char*)); 代码仍然给出核心转储

for(i=0;strcmp("",str[i])!=0;i++)

您取消引用未初始化的指针

for(i=0;str[i];i++)

但它不会像这样工作

memset(str,0,10);

不初始化整个数组

memset(str,0,10*sizeof(char *);
  1. is malloc() needed for char*[]`

在 C++ 中几乎不需要 malloc。

在 C 中,通常确实需要 malloc,但只有在需要动态分配时才需要。

一般来说,拥有 char*[] 并不意味着您一定需要动态分配,因此不需要 malloc。

if i do not malloc for every element of array str[] , then wouldn't it be wrong to assign a string without allocating memory for this string?

char* 不需要指向用 malloc 分配的内存。例如,它可以直接指向字符串文字(仅在 C 中;在 C++ 中,您需要一个指向 const 的指针)。或者它可以指向堆栈上的内存。

isn't char *str; strcpy(str,"sample") wrong if i dont allocate memory to str through malloc?

这是错误的,但这并不是因为您不使用 malloc。这是错误的,因为您将未初始化的指针传递给 strcpy。因此,行为是未定义的。跟malloc没关系。


  1. would strcmp fail ...

不清楚您所说的 "fail" 是什么意思。没有表示失败或错误的输出。对于某些输入,行为是未定义的。虽然未定义的行为是程序员的失败,但不能保证您可能认为失败的行为。

... if i memset to 0?

如果您传递给 strcmp 的指针不是指向空终止字符串的指针,则程序的行为是未定义的。

在您展示的程序中,您最终传递了未初始化的指针,或者 memset 为 0 的指针,因此不能保证它们是指向空终止字符串的指针。因此程序的行为是未定义的。

i'm passing a pointer pointing to 0(null), so dereferencing shouldn't face the problem of having no null terminated string right as we dont store anything in null location

Memset to 0 不保证为空,就标准而言。即使 probably 在您的系统上为 null,正如@ChristianGibbons 所指出的那样,10 个字节可能不足以容纳该系统上的 4 个指针,因此您实际上根本没有初始化所有指针。

即使您确实将指针初始化为空,空指针也不是指向空终止字符串的指针,因此将空指针传递给 strcmp 具有未定义的行为。

总结评论和其他答案中的所有内容,这里至少有三个(或者,如果你想迂腐的话,四个)问题:

  1. 您需要 memset(str, 0, 10*sizeof(char *)(但请参阅下面的 #4)。
  2. 您需要在调用 strcmp 之前检查空指针,在 for 循环中使用类似 str[i] != NULL && strcmp("",str[i])!=0 的条件。
  3. 如果您在数组中存储了 10 个非空字符串,循环将结束,永远找不到空字符串。
  4. (迂腐) memset 不是初始化空指针数组的好方法。 (严格来说,它根本不能保证有效。)正如@user3121023 在评论中所建议的,更好的方法是 char *str[10] = { NULL }.

与其使用空字符串(或空指针)作为字符串数组末尾的标记,不如考虑在单独的变量中保留显式计数。这可能是更常见的方法。


附录。您在询问是否需要分配字符串。确实需要为字符串分配内存,但您不一定需要通过调用 malloc 来动态分配它。至少有三种方法可以实现必要的分配,其中两种是编译器为您完成的。以下是这三者的示例:

char sample1[] = "Sample 1";

char *sample2 = malloc(strlen("Sample 2") + 1);
strcpy(sample2, "Sample 2");

str[0] = "Sample 0";
str[1] = sample1;
str[2] = sample2;