2013-03-01 2 views
1
char **test() 
{ 
    char *a[3]; 
    a[0] = (char *) malloc(sizeof(char) *3); 
    a[1] = (char *) malloc(sizeof(char) *3); 
    a[0] = "aa"; 
    a[1] = "bb"; 
    return a; 
} 

//main 
try{ 
    char ** a; 
    a = test(); 
    cout << a[0] << " " << a[1]; 
} 
catch(std::exception){} 

компилируется в VS2008, эта программа не в состоянии выхода «бб», но после того, как я удалить блок попытаться поймать, он оказался «аа бб», который правда. Причина и решение?попытка поймать оказывает влияние на гольца ** Возвращаемые значения

+2

Помимо утечек памяти, была ли конкретная точка на это (или, может быть, я просто пропустил его, как только я увидел те).? Вы возвращаете адрес локальной переменной, которая выходит за пределы области действия, когда вы eval 'a []' в своей основной. Не уверен, что это ваше намерение, но это ** неопределенное поведение **. – WhozCraig

+0

Почему мы используем malloc в C++? – andre

+0

@andre, потому что он может, и '' не бросает '# error' в качестве замены макросов, когда вы это делаете (пока). – WhozCraig

ответ

3

Эта программа имеет неопределенное поведение, потому что вы возвращаете указатель на локальный. Вам нужно выделить a массив с malloc для того, чтобы решить эту проблему:

char **test() { 
    char **a = (char**)malloc(sizeof(char*) * 2); 
    a[0] = (char *) malloc(sizeof(char) *3); 
    a[1] = (char *) malloc(sizeof(char) *3); 
    strcpy(a[0], "aa"); 
    strcpy(a[1], "bb"); 
    return a; 
} 

Конечно, теперь вы полностью ответственны за освобождение все, что malloc -ED памяти в вашем main, чтобы избежать утечек памяти (вы уже были на крючке для этого с вашей реализацией, теперь вам просто нужно добавить третье free вызывающему абоненту).

Несоответствия, которые вы видите, скорее всего, связаны с различиями в управлении стеками с блоком try/catch. Похоже, что без /catch данные в локальном хранилище доступны для печати, даже если он не является законным для ссылки на него после возврата функции test().

+0

+1 (как вы не видели * это * приход). – WhozCraig

+1

Я бы предпочел увидеть решение, которое не вносит утечку третьей памяти; но +1 для объяснения непосредственной проблемы. –

+1

Утечки памяти LOL все еще функционируют и полностью неповреждены = P – WhozCraig

0

Задача 1: возврат указателя на локальный массив. Это уничтожается, когда функция возвращается, и использование указателя после этого дает неопределенное поведение.

Задача 2: Явное управление памятью и переписывание указателей на выделенную память указателями на строковые литералы. Память, которую вы выделяете, просочилась; и если вы попытаетесь изменить литералы, вы получите больше неопределенного поведения.

Предполагая, что вы пишете на C++, а не C, то следующий будет исправить обе проблемы:

std::vector<std::string> test() {return {"aa", "bb"};} 
Смежные вопросы