Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > проблема с realloc(массив)


Автор: DPbIH 24.10.2007, 15:15
Такой вот код

Код

int main( int argc, char** argv ) {
//Создаем новый массив аргументов, в котором будут ссылки на ЛКФ и ГКФ
    argv = (char**)realloc(argv, sizeof(argv) * argc + 2 * sizeof(char) );

.....................................

}


При попытке расширить массив вываливается окошко debug assertation failed
а именно не проходит следующий assert

Код

        /*
         * If this ASSERT fails, a bad pointer has been passed in. It may be
         * totally bogus, or it may have been allocated from another heap.
         * The pointer MUST come from the 'local' heap.
         */
        _ASSERTE(_CrtIsValidHeapPointer(pUserData));


pUserData - указатель на нулевой элемент массива и до попытке рэаллока он был валидный. Так какого ху? 
Спасибо за ответы,товарищи проггеры!

Автор: Fazil6 24.10.2007, 15:58
Цитата(DPbIH @  24.10.2007,  15:15 Найти цитируемый пост)
pUserData - указатель на нулевой элемент массива и до попытке рэаллока он был валидный. Так какого ху? 

прикольно...
С чего ты взял, что это должно работать? argv это не HeapPointer

Автор: zkv 24.10.2007, 16:07
Цитата(Fazil6 @  24.10.2007,  15:58 Найти цитируемый пост)
С чего ты взял

уровень преподавания языка такой :( 
Я помню нечто подобное пытался провернуть когда-то, 
показывал преподу (преподавательнице вернее), та разводила руками, типа хз.  smile

Автор: NiJazz 25.10.2007, 08:10
DPbIH, realloc вызывается в DLL? В таком случае, видимо, память изначально была выделена в самом exe и передана в DLL по указателю. 
Я не помню точно где, но бытует утверждение, что realloc использовать не нужно. Извини, но объективно объяснить не могу, так как сам не пользуюсь CRT для работы с массивами и буферами вообще. Если нужно изменить размер буфера, обычно явно выделяют новый блок памяти, копируют туда содержимое старого буфера, затем старый буфер удаляют. Теоретически, realloc делает то же самое. smile 
Ты не смотрел в сторону STL?

Автор: zkv 25.10.2007, 08:28
1. объявление немного некорректное:
Цитата(DPbIH @  24.10.2007,  15:15 Найти цитируемый пост)
int main( int argc, char** argv )

на самом деле должно быть:
Код

int main( int argc, char* argv[] )

как говорится почувствуйте разницу smile

2. пусть даже char** argv, что это значит? 
Что у нас имеется динамический массив указателей на непрерывные участки в памяти, притом никто не обещает что они непрерывно будут следовать друг за другом, а realloc работает с memory block.
Это хорошо еще, что компилер хоть assert'ом по руками ударил. 
Цитата(DPbIH @  24.10.2007,  15:15 Найти цитируемый пост)
Так какого ху? 

вот такого  smile 

Автор: DPbIH 25.10.2007, 11:50
Цитата(NiJazz @ 25.10.2007,  08:10)
DPbIH, realloc вызывается в DLL? В таком случае, видимо, память изначально была выделена в самом exe и передана в DLL по указателю. 
Я не помню точно где, но бытует утверждение, что realloc использовать не нужно. Извини, но объективно объяснить не могу, так как сам не пользуюсь CRT для работы с массивами и буферами вообще. Если нужно изменить размер буфера, обычно явно выделяют новый блок памяти, копируют туда содержимое старого буфера, затем старый буфер удаляют. Теоретически, realloc делает то же самое. smile 
Ты не смотрел в сторону STL?

нет, не в DLL.
Мне нужно создать массив, указывая размер через переменную.
Вектор не катит, потому, что дальше этот масси мне нужно передать в функцию, которую писал не я, и которую переписывать нельзя.

Автор: zkv 25.10.2007, 11:52
Цитата(DPbIH @  25.10.2007,  11:50 Найти цитируемый пост)
Мне нужно создать массив, указывая размер через переменную.

так заведи собственные переменные и работай с ними, кто мешает?

Автор: DPbIH 25.10.2007, 12:03
сейчас сделал немного по-другому. Создал новый массив, а потом realloc"ом  попытался задать ему нужный размер

Код

int main( int argc, char** argv ) {
    //Создаем новый массив аргументов, в котором будут ссылки на ЛКФ и ГКФ
    char** newArgv = new char*[0];
    char**res = NULL;
    int newArgc = argc + 2;
    res = (char**)realloc(newArgv, sizeof(newArgv) * newArgc );
    
    newArgv[0] = argv[0];//ссылка на exe-файл
    newArgv[1] = strcat(getenv("W_HOME"), GCF_FILE_NAME);//ссылка на ГКФ
    newArgv[2] = strcat(getenv("W_HOME"), LCF_FILE_NAME);//ссылка на ЛКФ
    for(int i = 1; i < argc; i++)
        newArgv[i + 2] = argv[i];//остальное в конец массива

    for(int i = 0; i < newArgc; i++)
    {
        QMessageBox::warning(0, "", newArgv[i]);
    }

                WInjectMakerApp app( APP_NAME, newArgc, newArgv );


а вот результат меня удивил!!! 
в результате выполнения следующего кода

Код

for(int i = 0; i < newArgc; i++)
    {
        QMessageBox::warning(0, "", newArgv[i]);//просто посмотреть
    }


получаю

"Windows has triggered a breakpoint in winjectmaker.exe.

This may be due to a corruption of the heap, and indicates a bug in winjectmaker.exe or any of the DLLs it has loaded.

The output window may have more diagnostic information"

А вот в окне "WATCH" при просмотре элементов массива, все нормально! 

newArgv[0]    0x3a1f3830 "d:\3w\bin\winjectmaker.exe"                                                                                    char *
newArgv[1]    0x008b42af "D:\3w\app\winjectmaker\config\w.xml"                                                                    char *
newArgv[2]    0x008b42af "D:\3w\app\winjectmaker\config\winjectmaker.xml"                                                    char *
newArgv[3]    0x008b6450 "d:\3w\app\winjectmaker\config\rtdbsave.xml"                                                                    char *
newArgv[4]    0x008b647b "d:\3w\app\winjectmaker\config\out.xml"                                                                    char *


Автор: zkv 25.10.2007, 12:07
Цитата(DPbIH @  25.10.2007,  11:50 Найти цитируемый пост)
Вектор не катит, потому, что дальше этот масси мне нужно передать в функцию, которую писал не я, и которую переписывать нельзя. 

по поводу передачи вектора, можно воспользоваться тем, что элементы в нем обязаны храниться непрерывно:
Код

#include <vector>
#include <iostream>

static void Print( std::ostream &stream, const char *str );

int main( int argc, char*argv[])
{
    size_t size = strlen( argv[0] );
    std::vector<char> exeName( &argv[0][0],  &argv[0][size+1] );
    Print( std::cout, &exeName[0] );

    std::cin.get();
}

void Print( std::ostream &stream, const char *str )
{
    stream<<str;
}


Добавлено через 6 минут и 27 секунд
Цитата(DPbIH @  25.10.2007,  12:03 Найти цитируемый пост)
res = (char**)realloc(newArgv, sizeof(newArgv) * newArgc );

ты понимаешь, что делаешь?
sizeof(newArgv) == 4 (наверняка, зависит от платформы)
newArgc - колличество аргументов в ком.строке плюс 2
мы все это перемножаем, и получаем колличество байт, которые надо выделить?  smile

Автор: Lazin 25.10.2007, 12:18
Цитата(DPbIH @  25.10.2007,  12:03 Найти цитируемый пост)
char** newArgv = new char*[0];
***************
    res = (char**)realloc(newArgv, sizeof(newArgv) * newArgc );

Вот так лучше не делать, ты сначала выделяешь блок памяти через new, а потом передаешь его в realloc. В место new нужно вызывать malloc или realloc с параметром NULL.

Добавлено через 1 минуту и 27 секунд
а освобождать его free

Автор: Fazil6 25.10.2007, 12:34
Цитата(DPbIH @  25.10.2007,  12:03 Найти цитируемый пост)
сейчас сделал немного по-другому. Создал новый массив, а потом realloc"ом  попытался задать ему нужный размер

капец просто... Ошибка в каждой строке
Код

int main( int argc, char *argv[] ) {
    //Создаем новый массив аргументов, в котором будут ссылки на ЛКФ и ГКФ
    int newArgc = argc + 2;
    char** newArgv = new char*[newArgc];
    
    newArgv[0] = argv[0];//ссылка на exe-файл
    newArgv[1] = strcat(getenv("W_HOME"), GCF_FILE_NAME);//ссылка на ГКФ
    newArgv[2] = strcat(getenv("W_HOME"), LCF_FILE_NAME);//ссылка на ЛКФ
    
    for(int i = 1; i < argc; ++i)
        newArgv[i + 2] = argv[i];//остальное в конец массива

    for(int i = 0; i < newArgc; ++i)
    {
        QMessageBox::warning(0, "", newArgv[i]);
    }

     WInjectMakerApp app( APP_NAME, newArgc, newArgv );



Автор: DPbIH 25.10.2007, 13:16
Цитата(zkv @ 25.10.2007,  12:07)
Цитата(DPbIH @  25.10.2007,  11:50 Найти цитируемый пост)
Вектор не катит, потому, что дальше этот масси мне нужно передать в функцию, которую писал не я, и которую переписывать нельзя. 

по поводу передачи вектора, можно воспользоваться тем, что элементы в нем обязаны храниться непрерывно:
Код

#include <vector>
#include <iostream>

static void Print( std::ostream &stream, const char *str );

int main( int argc, char*argv[])
{
    size_t size = strlen( argv[0] );
    std::vector<char> exeName( &argv[0][0],  &argv[0][size+1] );
    Print( std::cout, &exeName[0] );

    std::cin.get();
}

void Print( std::ostream &stream, const char *str )
{
    stream<<str;
}


Добавлено @ 12:13
Цитата(DPbIH @  25.10.2007,  12:03 Найти цитируемый пост)
res = (char**)realloc(newArgv, sizeof(newArgv) * newArgc );

ты понимаешь, что делаешь?
sizeof(newArgv) == 4 (наверняка, зависит от платформы)
newArgc - колличество аргументов в ком.строке плюс 2
мы все это перемножаем, и получаем колличество байт, которые надо выделить?  smile

realloc возвращает указатель на блок выделенной им памяти, все правильно, не пойму в чем проблема!

Добавлено @ 13:20
Цитата(Lazin @ 25.10.2007,  12:18)
Цитата(DPbIH @  25.10.2007,  12:03 Найти цитируемый пост)
char** newArgv = new char*[0];
***************
    res = (char**)realloc(newArgv, sizeof(newArgv) * newArgc );

Вот так лучше не делать, ты сначала выделяешь блок памяти через new, а потом передаешь его в realloc. В место new нужно вызывать malloc или realloc с параметром NULL.

Добавлено @ 12:20
а освобождать его free

почему? new = malloc + конструктор.

Добавлено @ 13:24
2Fazil6

Код

char** newArgv = new char*[newArgc];


Реально не знал, что такое прокатывает!!!! smile  Думал, что размер нужно задавать константой. Поэтому и юзаю realloc!!!

Автор: zkv 25.10.2007, 13:47
Цитата(DPbIH @  25.10.2007,  13:16 Найти цитируемый пост)
все правильно, не пойму в чем проблема!

а я сразу не понял что ты там пытаешься сделать, зачем тогда new был? 
Запутать хотел? Получилось!  smile

Добавлено через 6 минут и 44 секунды
Цитата(DPbIH @  25.10.2007,  13:16 Найти цитируемый пост)
Думал, что размер нужно задавать константой.

а нафиг бы он нужен был такой new smile 

Автор: DPbIH 25.10.2007, 13:57
Цитата(zkv @ 25.10.2007,  13:47)
Цитата(DPbIH @  25.10.2007,  13:16 Найти цитируемый пост)
все правильно, не пойму в чем проблема!

а я сразу не понял что ты там пытаешься сделать, зачем тогда new был? 
Запутать хотел? Получилось!  smile

Добавлено @ 13:53
Цитата(DPbIH @  25.10.2007,  13:16 Найти цитируемый пост)
Думал, что размер нужно задавать константой.

а нафиг бы он нужен был такой new smile

капец йа креведко! smile  2-й день сижу!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)