2016-12-04 3 views
-1

Может быть, я просто запутанные вещи немного .. Но почему бы этот кусок кода C++:В чем причина конфликтов этого указателя?

#include <iostream> 
#include <list> 
using namespace std; 

void printArray(int *arr, int n) 
{ 
    for(int i=0; i<n; ++i) 
    cout << arr[i] << " "; 

    cout << endl; 
} 

int main() 
{ 
    list<int*> arrays; 
    int times=20, v[9]={1,2,3,4,5,6,7,8,0}; 

    arrays.push_back(v); 

    while(times--) 
    { 
     int *cur = arrays.front(); 
     arrays.pop_front(); 

     printArray(cur, 9); 

     int ta[9], tb[9]; 
     for(int i=0; i<9; ++i) 
     { 
      ta[i] = *(cur+i)+1; 
      tb[i] = *(cur+i)-1; 
     } 

     arrays.push_back(&ta[0]); 
     arrays.push_back(&tb[0]); 
    } 

    return 0; 
} 

Как вы можете видеть, цель состоит в том, чтобы, beggining с массивом по умолчанию {1,2, 3,4,5,6,7,8,0}, хранить (в раз итераций) 2 варианта этого массива в списке указателей int.

Итак, на первой итерации 2 массива {2,3,4,5,6,7,8,9,1} и {0,2,3, , 5,6,7, -1 } должны быть сохранены в списке и, таким образом, первые 3 PrintArray должно быть:

1 2 3 4 5 6 7 8 0 
2 3 4 5 6 7 8 9 1 
0 1 2 3 4 5 6 7 -1 

Теперь, случается, что первые 3 PrintArray являются:

1 2 3 4 5 6 7 8 0 
2 3 4 5 6 7 8 9 1 
2 3 4 5 6 7 8 9 1 

Я уже напечатаны ta и Т.Б. на каждую итерацию, и я знаю, что это на самом деле быть распечатаны являются 1) массива по умолчанию, 2) первых тот, 3) Тба первых тот. Но я действительно не знаю, в чем причина такого поведения, я имею в виду, не являются ли ta и tb новых массивов (независимо от предыдущих) на каждой итерации? Если это так, my for просто назначает значения для новых позиций массивов, так почему они конфликтуют друг с другом?

+1

Обратите внимание, что то и Эйнт памяти Tb массивов под управлением вектором станда. Я предполагаю, что при последовательных итерациях массивы могут быть освобождены, а поведение не определено. Попробуйте выделить их вне цикла while – quimnuss

+0

Также у вас нет трех массивов указателей int, у вас есть три указателя на соответствующие int массивы. – quimnuss

+0

Это имеет смысл Если это причина. И да, это работает, если я ранее выделял количество необходимых массивов вне цикла while или просто если бы я просто 'int * ta = new int [9] ...' на каждой итерации, что в основном одно и то же.Я предполагаю, что, поскольку ta и tb являются локальными переменными для цикла while, они будут иметь силу только до конца области, и это конец самой итерации ... Согласны ли вы? @quimnuss – yat0

ответ

0

Проблема довольно проста, на самом деле.

Как @quimnuss говорится в комментарии, та и Т.Б. были deallocating в какой-то момент и, таким образом, указатели, сохраненные в списке будут указывать на что-то совершенно другой из этих массивов, которые были высвобождены, что приводит к неопределенным и поведение программы.

Это утверждение имеет полный смысл, так как та и Т.Б. локальные переменные время цикла и поэтому их действие будет выполняться при каждой итерации завершения.

Мы можем обойти эту проблему путем динамического выделения памяти на каждой итерации, как:

int *ta = new int[9]; 
int *tb = new int[9]; 

Это не потеря информации будет происходить на каждой итерации конца, так как объем этих массивов уже не локальный в сторону в то время как цикл.

Окончательный код:

#include <iostream> 
#include <list> 
using namespace std; 

void printArray(int *arr, int n) 
{ 
    for(int i=0; i<n; ++i) 
    cout << arr[i] << " "; 

    cout << endl; 
} 


int main() 
{ 
    list<int*> arrays; 
    int times=20;  

    int *v = new int[9]; 
    for(int i=0; i<8; ++i) 
     v[i] = i+1; 
    v[8] = 0; 

    arrays.push_back(v); 

    while(times--) 
    { 
     int *cur = arrays.front(); 
     arrays.pop_front(); 

     printArray(cur, 9); 

     int *ta = new int[9]; 
     int *tb = new int[9]; 

     for(int i=0; i<9; ++i) 
     { 
      ta[i] = *(cur+i)+1; 
      tb[i] = *(cur+i)-1; 
     } 

     arrays.push_back(ta); 
     arrays.push_back(tb); 

     delete[] cur; 
    } 

    while(!arrays.empty()) 
    { 
     int *p = arrays.front(); 
     arrays.pop_front(); 
     delete[] p; 
    } 

    return 0; 
} 
+2

вы играете с огнем здесь. Первым элементом массива является 'v', который является выделенным стеком. Остальные динамически выделяются, поэтому нужно «delete'd. Вы уверены, что не можете просто использовать std :: vector или std :: array ? Это значительно облегчило бы управление памятью. –

+0

Да, и я сделал это. Это был просто способ, который мой друг пытался сделать, в контексте проблемы, и я был заинтригован этим и просто спросил здесь, почему это не работает. Я обновлю код, я удалю память сразу после ее использования. @JosephIreland – yat0

+0

Итак, это правильно, хотя это очень, очень уродливо. Я согласен с Джозефом, что вы играете с огнем. Тем не менее, у вас есть, однако, огромная утечка памяти, так как вы создаете векторы с выделенными кучками 'times * 2 + 1', и вы удаляете только' times'. Я настаиваю, переместите выделение и удаление из цикла, иначе вы будете смешивать области и, хотя это будет работать, потому что выделено его кучей, его довольно трудно прочитать. Обратите внимание, что назначение может оставаться таким, каким оно есть. В дополнение к утечке памяти у вас все еще есть. – quimnuss

Смежные вопросы