英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论