C prime 生成器中 realloc 的看似未定义的行为(程序已发布,可运行)
Seemingly undefined behavior with realloc in C prime generator (program posted, runnable)
我编写了一个程序来查找素数,并使用 realloc() 来更改“*primes”块的大小。当我输入大于 6 的任何位数时,我发现前两个值似乎是未定义的行为,我无法理解为什么会发生这种情况(后面的数字都是正确的)。请减半。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int int64_t;
void *safe_calloc(size_t,size_t);
void *safe_realloc(void*,size_t);
int main()
{
printf("Prime Generator\nPlease enter the number of usable bits: ");
int bits =0, maxNum=1, size = 6, elems = 3;
scanf("%d",&bits);
if(bits<1)
exit(0);
int i=0;
for(; i < bits; i++)
maxNum*=2;
int *primes = safe_calloc(size*sizeof(int),sizeof(int));
int *temp = safe_calloc(size*sizeof(int),sizeof(int));
primes[0] = 1;
primes[1] = 2;
primes[2] = 3;
int n = 3,j;
for(; n < maxNum; n+=2){
for(j = 2; j < elems; j++){
if(n%primes[j] == 0)
break;
else if(j == elems-1){
primes[elems++] = n;
if((size-elems) < 2){
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
size += 8; // add 8 spaces to the prime storage array
temp = safe_realloc(primes,size*sizeof(int));
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
memmove(temp,primes,(size-8)*sizeof(int)); // copy over data to new array, just to be sure
primes = temp;
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
}
}
}
}
if(bits == 1){
printf("1");
}
else{
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
}
free(temp);
free(primes);
return 0;
}
void *safe_calloc(size_t length,size_t dataSize){
int *tmp;
if ((tmp = calloc(length,dataSize)) == NULL) {
printf("ERROR: calloc failed");
exit(0);
}
return tmp;
}
void *safe_realloc(void* ptr, size_t arraySize){
int *tmp;
if ((tmp = realloc(ptr,arraySize)) == NULL) {
printf("ERROR: realloc failed");
exit(0);
}
return tmp;
}
您不需要 memmove
数据。 realloc
自动执行此操作并释放旧缓冲区。所以 memmove
是从无效的(已经释放的)内存 space.
复制的
不要使用调用后放入 realloc
的指针 - 仅使用返回的指针。您也不需要复制/memmove
:
The contents of the object shall remain unchanged up to the lesser of
the new and old sizes. If the new size of the memory object would
require movement of the object, the space for the previous
instantiation of the object is freed.
正如其他人指出的那样,以您现在的方式使用 memmove 是不正确的。 realloc 保留当前内容,并添加额外的内存,以便您可以根据需要继续使用 strcat 或 strcpy。
为了realloc()
防止内存丢失,使用临时buf,检查NULL,然后重新分配给原来的...
temp = realloc(temp, 20);
if(!temp)
{
//handle error and exit
}
buf = temp;//transfer successfully allocated memory
....
//use newly reallocated buf
我编写了一个程序来查找素数,并使用 realloc() 来更改“*primes”块的大小。当我输入大于 6 的任何位数时,我发现前两个值似乎是未定义的行为,我无法理解为什么会发生这种情况(后面的数字都是正确的)。请减半。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int int64_t;
void *safe_calloc(size_t,size_t);
void *safe_realloc(void*,size_t);
int main()
{
printf("Prime Generator\nPlease enter the number of usable bits: ");
int bits =0, maxNum=1, size = 6, elems = 3;
scanf("%d",&bits);
if(bits<1)
exit(0);
int i=0;
for(; i < bits; i++)
maxNum*=2;
int *primes = safe_calloc(size*sizeof(int),sizeof(int));
int *temp = safe_calloc(size*sizeof(int),sizeof(int));
primes[0] = 1;
primes[1] = 2;
primes[2] = 3;
int n = 3,j;
for(; n < maxNum; n+=2){
for(j = 2; j < elems; j++){
if(n%primes[j] == 0)
break;
else if(j == elems-1){
primes[elems++] = n;
if((size-elems) < 2){
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
size += 8; // add 8 spaces to the prime storage array
temp = safe_realloc(primes,size*sizeof(int));
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
memmove(temp,primes,(size-8)*sizeof(int)); // copy over data to new array, just to be sure
primes = temp;
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
}
}
}
}
if(bits == 1){
printf("1");
}
else{
for(i = 0; i < elems; i++)
printf("%d\n",primes[i]);
printf("\n");
}
free(temp);
free(primes);
return 0;
}
void *safe_calloc(size_t length,size_t dataSize){
int *tmp;
if ((tmp = calloc(length,dataSize)) == NULL) {
printf("ERROR: calloc failed");
exit(0);
}
return tmp;
}
void *safe_realloc(void* ptr, size_t arraySize){
int *tmp;
if ((tmp = realloc(ptr,arraySize)) == NULL) {
printf("ERROR: realloc failed");
exit(0);
}
return tmp;
}
您不需要 memmove
数据。 realloc
自动执行此操作并释放旧缓冲区。所以 memmove
是从无效的(已经释放的)内存 space.
不要使用调用后放入 realloc
的指针 - 仅使用返回的指针。您也不需要复制/memmove
:
The contents of the object shall remain unchanged up to the lesser of the new and old sizes. If the new size of the memory object would require movement of the object, the space for the previous instantiation of the object is freed.
正如其他人指出的那样,以您现在的方式使用 memmove 是不正确的。 realloc 保留当前内容,并添加额外的内存,以便您可以根据需要继续使用 strcat 或 strcpy。
为了realloc()
防止内存丢失,使用临时buf,检查NULL,然后重新分配给原来的...
temp = realloc(temp, 20);
if(!temp)
{
//handle error and exit
}
buf = temp;//transfer successfully allocated memory
....
//use newly reallocated buf