memset字符串的strcmp上的SIGSEV

时间:2019-06-28 16:20:29

标签: c strcmp memset

在下面的程序中,我期望for循环在3个元素后停止。 但是它会无限期地继续下去,以后会因coredump而失败。

  1. malloc() needed for字符* []`
  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*));,代码仍然可以进行核心转储

3 个答案:

答案 0 :(得分:3)

总结评论和其他答案中所述的所有内容,这里至少存在三个(或者,如果您想成为书呆子,则是四个)问题:

  1. 您需要memset(str, 0, 10*sizeof(char *)(但请参见下面的#4)。
  2. 您需要在strcmp循环中使用str[i] != NULL && strcmp("",str[i])!=0之类的条件,在调用for之前检查空指针。
  3. 如果您曾经在数组中存储10个非空字符串,则循环将结束,永远不会找到空字符串。
  4. (pedantic)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;

答案 1 :(得分:2)

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

您确实取消了对统一指针的引用

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

但是它不能像这样

memset(str,0,10);

不初始化整个数组

memset(str,0,10*sizeof(char *);

答案 2 :(得分:2)

  
      
  1. char * []是否需要malloc()
  2.   

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

在C语言中,通常确实需要malloc,但前提是您需要动态分配。

通常,拥有char * []并不意味着您必然需要动态分配,因此不需要malloc。

  

如果我不为数组str []的每个元素分配内存,那么在不为该字符串分配内存的情况下分配一个字符串会不会出错?

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

  

不是char * str;如果我不通过malloc为str分配内存,strcpy(str,“ sample”)错误吗?

那是错误的,但不是因为您不使用malloc。这是错误的,因为您将未初始化的指针传递给strcpy。因此,行为是不确定的。它与malloc无关。


  
      
  1. strcmp会失败...
  2.   

您不清楚“失败”是什么意思。没有输出指示失败或错误。对于某些输入,行为是不确定的。尽管未定义的行为是程序员的失败,但不能保证您可能会认为失败。

  

...如果我将其设为0?

如果将指针传递给strcmp而不是以null结尾的字符串的指针,则该程序的行为是不确定的。

在显示的程序中,最终传递未初始化的指针或memset设为0的指针,因此无法保证它们是指向以空终止的字符串的指针。因此,程序的行为是不确定的。

  

我正在传递指向0(null)的指针,因此取消引用应该不会遇到没有以null结尾的字符串的问题,因为我们不在空位置存储任何东西

就标准而言,Memset不能保证为null。正如@ChristianGibbons指出的那样,即使您的系统上可能为null,但该系统上的4个指针也可能不足10个字节,因此您实际上并没有初始化所有指针。

即使您确实将指针初始化为null,null指针也不是指向以null结尾的字符串的指针,因此将null指针传递给strcmp仍具有不确定的行为。