英文:
can figure out the problem with my realloc inside the function
问题
我正在编写一个需要调用一个函数的程序,该函数会一直添加数字,直到输入-1为止,问题是在输入3个数字后程序停止并出现分段错误:
int leNumeros(int **lista, int *nElem, int *tam)
{
    int op, *temp = NULL;
    *lista = (int*) malloc(*tam * sizeof(int));
    
    if(*lista == NULL)
    {
        printf("memory fail\n");
    } else
    {
        do
        {
            printf("number:\n");
            scanf("%d", &op);
            if(op >= 0)
            {
                if(*nElem >= *tam)
                {
                *lista = (int*) realloc( *lista, *nElem * sizeof(int) );
                
                if(*lista == NULL)
                {
                    printf("memory fail");
                }
                else
                {
                    printf("added: %d bytes total: %d bytes\n",
                            *nElem * sizeof(int), *nElem * sizeof(int) + *tam * sizeof(int));
                    //*lista = temp;
                }
                }
                (*lista)[*nElem] = op;
                (*nElem)++;
            }
        } while(op >= 0);
    }    
}
int main(int argc, char** argv) {
    
    int *lista = NULL, nElem = 0, tam = 0;
    
    leNumeros(&lista, &nElem, &tam);
    
    return (EXIT_SUCCESS);
}
我有困难理解发生了什么,请问有人可以帮助我吗?
英文:
I'm writing a program that needs to call a function that adds numbers until -1 is introduced, the problem is that after 3 numbers the program stops and gives segmentation fault:
int leNumeros(int **lista, int *nElem, int *tam)
{
    int op, *temp = NULL;
    *lista = (int*) malloc(*tam * sizeof(int));
    
    if(*lista == NULL)
    {
        printf("memory fail\n");
    } else
    {
        do
        {
            printf("number:\n");
            scanf("%d",&op);
            if(op >= 0)
            {
                if(*nElem >= *tam)
                {
                *lista = (int*) realloc( *lista, *nElem * sizeof(int) );
                
                if(*lista == NULL)
                {
                    printf("memory fail");
                }
                else
                {
                    printf("added: %d bytes total: %d bytes\n",
                            *nElem * sizeof(int), *nElem * sizeof(int) + *tam * sizeof(int));
                    //*lista = temp;
                }
                }
                *lista[*nElem] = op;
                (*nElem)++;
                
                
                
            }
        }while(op >= 0);
    }    
}
int main(int argc, char** argv) {
    
    int *lista = NULL, nElem = 0, tam = 0;
    
    leNumeros(&lista, &nElem, &tam);
    
    return (EXIT_SUCCESS);
}
I'm having trouble understanding what is going on, can anyone help me please?
答案1
得分: 2
当调用leNumeros()时,您尝试分配一个零长度的块 - 这具有_实现定义的行为_。
然后,当您输入一个大于0的数字时,您尝试realloc()一个零长度的块 - 这个行为是_明确定义的_,它会释放原始块然后返回一个空指针,然后在*lista[*nElem] = op;处,您对该空指针进行了解引用,而不是中止循环。
无论如何,*lista[*nElem] = op; 应该是 (*lista)[*nElem] = op;
即使 *nElem 是非零的,以下这行代码也是不良实践,因为如果重新分配失败,原始块将泄漏,因为 *lista 将变为 NULL,而不释放它之前指向的任何内容。相反,您应该(例如):
int* new_block = realloc(*lista, *nElem * sizeof(int));
if (new_block == NULL)
{
    printf("内存失败\n");
    break;
}
*lista = new_block;
要使主函数正常工作,tam 必须大于 0,为了避免由于实现定义的行为而可能的失败,nElem 也应该大于零。
英文:
When leNumeros() is called you attempt to allocate a zero length block - that has implementation defined behaviour.
Then when you enter a number > 0, you attempt to realloc() a zero length block - that behaviour is well defined it frees the original block then returns a null pointer, then at *lista[*nElem] = op; you deference that null pointer rather than aborting the loop.
In any event *lista[*nElem] = op; should be (*lista)[*nElem] = op;
Even if  *nElem was non-zero, the line:
*lista = (int*)realloc(*lista, *nElem * sizeof(int));
is bad-practice, because if the reallocation fails the original block will leak because *lista will be come NULL without releasing whatever it previously pointed to. Instead you should (for example):
int* new_block = realloc(*lista, *nElem * sizeof(int));
if( new_block == NULL )
{
    printf( "memory fail\n" ) ;
    break ;
}
*lista = new_block ;
To work at all in main tam must be > 0, and to avoid possible failure due to implementation defined behaviour nElem should also be grater than zero.
答案2
得分: 1
我认为 tam 参数可能是要分配的块大小。例如,如果 tam = 10,那么分配空间给 10 个整数。然后在取 10 个整数后,重新分配 10 个。
此外,请注意,由于运算符优先级,*lista[*nElem] = op; 与 *(lista[*nElem]) = op; 是相同的。您应该先解引用指针,然后使用方括号:(*lista)[*nElem] = op;
void leNumeros(int **lista, int *nElem, int *tam)
{
    if (*tam <= 0) {
        puts("Error: tam must be > 0");
        return;
    }
    int op;
    // 记录数组可以容纳多少个整数
    int items_allocated = *tam;
    *lista = malloc(*tam * sizeof(int));
    if (*lista == NULL)
    {
        printf("memory fail\n");
    }
    else
    {
        do
        {
            printf("number:\n");
            if (1 != scanf("%d", &op)) break;
            if (op >= 0) {
                // 如果空间不足,重新分配 tam 个字节的新块
                if (*nElem >= items_allocated) {
                    items_allocated += *tam;
                    int *temp = realloc(*lista, items_allocated * sizeof(int));
                    if (temp == NULL) {
                        printf("memory fail");
                        break;
                    }
                    else {
                        *lista = temp;
                        printf("added: %zu bytes total: %zu bytes\n", *tam * sizeof(int), items_allocated * sizeof(int));
                    }
                }
                (*lista)[*nElem] = op;
                (*nElem)++;
            }
        } while (op >= 0);
    }
}
int main(int argc, char** argv) {
    int *lista = NULL, nElem = 0, tam = 5;
    leNumeros(&lista, &nElem, &tam);
    for (int i = 0; i < nElem; i++) {
        printf("%d ", lista[i]);
    }
    return (EXIT_SUCCESS);
}
英文:
I think the tam parameter is probably the block size to allocate. So for example, if tam = 10, allocate space for 10 ints. Then after taking 10 ints, realloc for 10 more.
Also, note that because of operator precedence, *lista[*nElem] = op; is the same as *(lista[*nElem]) = op;. You want to deference the pointer first, then use the brackets: (*lista)[*nElem] = op;
void leNumeros(int **lista, int *nElem, int *tam)
{
    if (*tam <= 0) {
        puts("Error: tam must be > 0");
        return;
    }
	int op;
    // Keep track of how many ints the array can hold
	int items_allocated = *tam;
	*lista = malloc(*tam * sizeof(int));
	if (*lista == NULL)
	{
		printf("memory fail\n");
	}
	else
	{
		do
		{
			printf("number:\n");
			if (1 != scanf("%d", &op)) break;
			if (op >= 0) {
				// Realloc a new block of tam bytes if out of space
				if (*nElem >= items_allocated) {
					items_allocated += *tam;
					int *temp = realloc(*lista, items_allocated * sizeof(int));
					if (temp == NULL) {
						printf("memory fail");
						break;
					}
					else {
                        *lista = temp;
						printf("added: %zu bytes total: %zu bytes\n", *tam * sizeof(int), items_allocated * sizeof(int));
					}
				}
				(*lista)[*nElem] = op;
				(*nElem)++;
			}
		} while (op >= 0);
	}
}
int main(int argc, char** argv) {
	int *lista = NULL, nElem = 0, tam = 5;
	leNumeros(&lista, &nElem, &tam);
	for (int i = 0; i < nElem; i++) {
		printf("%d ", lista[i]);
	}
	return (EXIT_SUCCESS);
}
</details>
				通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论