2016-04-02 1 views
1

Я написал программу для поиска простых чисел, и я использую realloc() для изменения размера блока «* простых чисел». Когда я помещаю любое количество бит больше 6, я обнаружил, что первые два значения кажутся неопределенным поведением, и я не могу, чтобы жизнь меня поняла, почему это происходит (цифры, которые следуют, правильны). pls halp.По-видимому, неопределенное поведение с realloc в генераторе C prime (программа отправлена, runnable)

#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; 
} 
+0

Примечание: 'exit' код '0' обычно используются для сообщения" нет ошибки "(это также то, что' main' возвращает неявно). Вместо этого вы должны вернуть небольшое положительное целое, обычно '1', если другие значения не используются. – Olaf

+0

1) Не ошибка: 'int * primes = safe_calloc (size * sizeof (int), sizeof (int));', вероятно, слишком велико ... 2: 'primes [0] = 1;' I don Думаю, это хорошая идея. – wildplasser

ответ

1

Не используйте указатель, который вы положили в 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.

1

Вам не нужно указывать memmove данных. realloc делает это автоматически и освобождает старый буфер. Таким образом, memmove копирует с недопустимого (уже освобожденного) пространства памяти.

0

Как уже отмечалось, с помощью memmove в пути вы не правильно. realloc сохраняет текущий контент и добавляет дополнительную память, поэтому вы можете продолжить с помощью strcat или strcpy по мере необходимости.

Для realloc(), чтобы предотвратить потерю памяти, используйте временные БУФЫ, проверьте NULL, то переназначить на оригинал ...

temp = realloc(temp, 20); 
if(!temp) 
{ 
    //handle error and exit 
} 
buf = temp;//transfer successfully allocated memory 
.... 
//use newly reallocated buf 
+0

@ user3386109 - Я прочитал их, и хотя вы проверяете значение null, вы не используете 'realloc()' правильно. 'memmove()' не требуется. Упомянув эту функцию 'realloc()', я не хотел передавать, что менее важно также проверить возврат функций распределения в целом. _Но да, это вы сделали правильно! _ :) Однако метод, который вы используете с 'realloc()' в сочетании с 'memmove()', вызовет у вас проблемы. – ryyker