C - 内存分配问题 - 需要解释

时间:2013-03-24 17:55:21

标签: c pointers structure c-strings

最近,我遇到了C指针的问题。 正如您可能看到的,我有一个从STDIN读取数据的循环。问题是我不太明白我做了什么。

我为这个struct_CONTAINER结构分配了内存。我希望有一个内部有BUFFER_SIZE长度的c字符串数组。如果正确地明白,这个数组包含BUFFER_SIZE(字符*)对象 - 这意味着该阵列的重量将是8个* BUFFER_SIZE字节(8个字节至多为每个字符指针)。因此,例如,如果BUFFER_SIZE定义为值10,那么这为该数组提供了80个字节,并且整个结构可能具有相似的大小。

问题是我能够使用大于BUFFER_SIZE的值迭代该指针,这对我来说是多么奇怪 - 内存不是NULL。我知道在那个循环中我可能正在尝试访问其他已经分配的内存。但我不确定。如果有人会很好,并告诉我我在做什么是对错。内存分配可能太大。提前谢谢!

char *item = NULL;

if( dup2( STDIN_FILENO, fdin ) < 0 ){
    perror( "dup2(  )" );
    exit( errno );
}

memset( reading, '\0', BUFFER_SIZE );

struct struct_CONTAINER{
    char *container[BUFFER_SIZE];
};


while( ( r_control = read( fdin, reading, BUFFER_SIZE-1 ) ) > 0 ){
    item = &shmemContainer->container[i++];
    strcpy(item, reading);
    memset( reading, '\0', BUFFER_SIZE );
}
编辑:我忘了告诉你“项目”变量的类型是什么

2 个答案:

答案 0 :(得分:1)

您的结构成员container属于char*类型,表示其字符串数组。您要分配item字符串的char**地址,并尝试拨打strcpy(item, reading);

至少在下列其中一项陈述中你做错了。

 item = &shmemContainer->container[i++];
        ^   is wrong 
 strcpy(item, reading);
         ^ or this is wrong

[答案] ,因为您评论的第一个点是代码中的错误
因为precedence of -> operator is higher then &。编译代码时应该收到警告。

  • 如果第一个表达式item = &shmemContainer->container[i++];错误,请将其写成:

    item = (&shmemContainer)->container[i++];

  • 如果strcpy(item, reading);错误,请将其更正为:

    strcpy(*item, reading);

正如我从你的while循环中可以理解的那样,你想要从fdin读取字符串数组,你可以这样做:

while( ( r_control = read( fdin, reading, BUFFER_SIZE-1 ) ) > 0 ){
    reading[r_control] = '\0'; // null ternimate
    strcpy(shmemContainer->container[i++],reading) ;
    memset( reading, '\0', BUFFER_SIZE );
}

代码reading[r_control] = '\0';添加了此内容,因为您第一次错过memset()时,请记住read()不会自行终止\0字符串。

修改
考虑@ Digikata的评论,因为您正在strcpy()container[]确保为每个字符串分配内存。

我的建议:

container[]是字符串数组,因此您可以在while循环中分配内存,例如:

i = 0;
while( ( r_control = read( fdin, reading, BUFFER_SIZE-1 ) ) > 0 ){
    reading[r_control] = '\0'; // null ternimate
    shmemContainer->container[i] = malloc(strlen(reading) + 1);
    strcpy(shmemContainer->container[i++],reading) ;
    memset( reading, '\0', BUFFER_SIZE );
}

如果您缺少,请添加内存分配。

答案 1 :(得分:0)

C不会阻止您索引超出预期的内存位置。例如:

char astring[5] = "0123";  // there is a zero at index 4 
char* ptr = astring;       // ptr[4] == 0

printf("%c", ptr[5]);  // reads a byte beyond the end of the string array 

您的代码需要在逻辑上防止这种情况发生,因为那里经常有数据, 但写它(有时甚至读它)将导致未定义的行为。因此,在您的代码中,容器之外的区域读取为非NULL是正常的。

顺便说一下,你的问题不清楚你是否理解指向​​c-string的char *类型与分配的内存区域之间的区别,例如上面代码中的“ptr”和“astring”变量。您的示例代码不会为字符串分配任何内存。