LINUX.ORG.RU

gcc, bad_alloc


0

0

Почему то следующий код выдаёт исключение bad_alloc, после создания ~ 22 000 экземпляров массива, число может немного меняться и от размера создаваемого массива не зависит. С выделением памяти проблем вроде бы быть не должно. Собирал gcc-4.1 и 4.3. Собранный MinGW под виндой работает нормально. Собственно если есть ошибка то где она?

#include <iostream> 

using namespace std;

void munic(int* res);
int cntErr;

int main(int argc, char** argv)
{
    cntErr = 0;
    int cntSize = 30000;
    int* res;
    for(int cnt = 0; cnt < cntSize; cnt++)
    {
        cout << cnt << '\t';
        munic(res);
    }
    return 0;
}

void munic(int* res)
{
    try
    {
        int arrSize = 100;
        res = new int(arrSize);
        for(int cnt = 0; cnt < arrSize; cnt++)
        {    
            res[cnt] = 0;
        }
    }
    catch(bad_alloc& err)
    {
        cout << err.what() << '\t' << cntErr << '\n';
        cntErr++;
    }
}

Ответ на: комментарий от nikolayd

>Да и вообще мне непонятно, начерта тут юзать С++-style

стиль C++ был бы в использовании vector<char>, а тут стиль C

vasil
()
Ответ на: комментарий от nikolayd

>res = new int[arrSize];
memset(res,0,sizeof(int)*100);
delete[] res;

Теперь выдаёт вот это:

*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x08048a89 ***
======= Backtrace: =========
/lib/i686/cmov/libc.so.6[0xb7cbc1d4]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7ea8c11]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xb7ea8c6d]
./a.out[0x8048a3a]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7c63775]
./a.out[0x80487e1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 5390338 /home/user/programs/test/a.out
08049000-0804a000 rw-p 00000000 08:02 5390338 /home/user/programs/test/a.out
087b8000-087fa000 rw-p 087b8000 00:00 0 [heap]
b7c4c000-b7c4d000 rw-p b7c4c000 00:00 0
b7c4d000-b7da7000 r-xp 00000000 08:03 1226668 /lib/i686/cmov/libc-2.9.so
b7da7000-b7da9000 r--p 0015a000 08:03 1226668 /lib/i686/cmov/libc-2.9.so
b7da9000-b7daa000 rw-p 0015c000 08:03 1226668 /lib/i686/cmov/libc-2.9.so
b7daa000-b7dad000 rw-p b7daa000 00:00 0
b7dad000-b7dca000 r-xp 00000000 08:03 1226414 /lib/libgcc_s.so.1
b7dca000-b7dcb000 rw-p 0001c000 08:03 1226414 /lib/libgcc_s.so.1
b7dcb000-b7dcc000 rw-p b7dcb000 00:00 0
b7dcc000-b7df0000 r-xp 00000000 08:03 1226600 /lib/i686/cmov/libm-2.9.so
b7df0000-b7df1000 r--p 00023000 08:03 1226600 /lib/i686/cmov/libm-2.9.so
b7df1000-b7df2000 rw-p 00024000 08:03 1226600 /lib/i686/cmov/libm-2.9.so
b7df2000-b7ed6000 r-xp 00000000 08:03 1395116 /usr/lib/libstdc++.so.6.0.11
b7ed6000-b7eda000 r--p 000e4000 08:03 1395116 /usr/lib/libstdc++.so.6.0.11
b7eda000-b7edb000 rw-p 000e8000 08:03 1395116 /usr/lib/libstdc++.so.6.0.11
b7edb000-b7ee2000 rw-p b7edb000 00:00 0
b7ef8000-b7efb000 rw-p b7ef8000 00:00 0
b7efb000-b7efc000 r-xp b7efb000 00:00 0 [vdso]
b7efc000-b7f18000 r-xp 00000000 08:03 1226636 /lib/ld-2.9.so
b7f18000-b7f19000 r--p 0001b000 08:03 1226636 /lib/ld-2.9.so
b7f19000-b7f1a000 rw-p 0001c000 08:03 1226636 /lib/ld-2.9.so
bff04000-bff19000 rw-p bffeb000 00:00 0 [stack]
0 Аварийный останов

XBOCT
() автор топика
Ответ на: комментарий от XBOCT

#include <iostream>
#include <vector>

using namespace std;

void munic(vector<int>* res);
int cntErr = 0;

int main(int argc, char** argv)
{
    int cntSize = 30000;
    vector<int> res;
    for(int cnt = 0; cnt < cntSize; cnt++)
    {
        cout << cnt << '\t';
        munic(&res);
    }
    return 0;
}

void munic(vector<int>* res)
{
    try
    {
        int arrSize = 100;
        res->resize(arrSize, 0);
    }
    catch(bad_alloc& err)
    {
        cout << err.what() << '\t' << cntErr << '\n';
        cntErr++;
    }
}

vasil
()
Ответ на: комментарий от vasil

Спасибо, но такой вариант у меня уже есть и он работает. Я вобще-то хотел сравнить скорость выполнения варианта с использованием массива и vector.

XBOCT
() автор топика

У тебя минимум 1 ошибка и куча неправильного стиля, так что вообще не понятно что ты хочешь.

Как минимум res = new int(arrSize); ===> res = new int[arrSize];

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Блин, только сейчас заметил, спасибо.

XBOCT
() автор топика
Ответ на: комментарий от vasil

В общем то в последнее время я и склоняюсь в пользу vector

XBOCT
() автор топика
Ответ на: комментарий от www_linux_org_ru

res = new int(arrSize) означает размещение int по адресу arrSize
и далее в программе начиная с адреса arrSize в память пишется 0

vasil
()
Ответ на: комментарий от vasil

Я уже понял, спать мне надо чаще.:-)

XBOCT
() автор топика

#include <stdio.h>
#include <stdlib.h>

void munic();
int cntErr = 0;

int main(void)
{
	int cntSize = 50000;	
	for(int i = 0; i < cntSize; ++i)
	{
		printf("%d\x9", i);
		munic();
	}
}

void munic()
{
	int arrSize = 100;
	int *res = malloc(arrSize*sizeof(int));
	if(res)
	{
		for(int i = 0; i < arrSize; ++i)
		{
			res[i]=0;
		}
		free(res);
	}
	else
	{
		printf("malloc failure\x9\n");
		++cntErr;
	}
}

Просто не пользуйся плюсами. Иногда помогает.

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

> ++i

> ++cntErr;

а почерк то у тебя плюсовый, выдает:)

(я к тому что это у плюсовиков пошла привычка префиксный инкремент предпочитать постфиксному)

dilmah ★★★★★
()

Точнее "res = new (XXX) int;" размещает по адресу XXX
А res = new int(arrSize) создаёт в динамической памяти 1 объект типа int и вызывает для него конструктор с параметром arrSize;



vasil
()
Ответ на: комментарий от dilmah

префиксный элемент не требует возврата значения объекта до работы
оператора, что эффективнее, если значение предыдущее значение не нужно

vasil
()
Ответ на: комментарий от www_linux_org_ru

>Прикол в том, что компилятор соглашается :-)

А чём прикол? Так и долэно быть. Это выделение одного объекта типа int, инициализированного значением arrSize. Компилер тут безсилен.

devinull ★★
()
Ответ на: комментарий от vasil

> res = new int(arrSize) означает размещение int по адресу arrSize

Надо-же, а я всю жизнь думал что конструкция

Object* = new Object(arg1, arg2, ..., argN);

это передача аргументов конструктору (который есть и у int-а), а размещение обьекта по заданному адресу делается не иначе как:

res = new(addr) int;

vnovouhov
()
Ответ на: комментарий от vasil

> префиксный элемент не требует возврата значения объекта до работы оператора, что эффективнее, если значение предыдущее значение не нужно

я и говорю, что это плюсовая привычка. Потому что для целого числа, очевидно, что компилятор способен оптимизировать это. Для сложных объектов/итераторов могут быть проблемы.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> я и говорю, что это плюсовая привычка. Потому что для целого числа, очевидно, что компилятор способен оптимизировать это. Для сложных объектов/итераторов могут быть проблемы.

Другими словами, разница есть только в плюсах. В C ни к каким сложным объектам ++ не припишешь, а постфиксный оператор красивше :)

const86 ★★★★★
()
Ответ на: комментарий от dilmah

> > ++i
> > ++cntErr;

> а почерк то у тебя плюсовый, выдает:)

> (я к тому что это у плюсовиков пошла привычка префиксный инкремент предпочитать постфиксному)


Справедливо при инкрементировании итератора контейнера. Поскольку iterator++ вызовет ++iterator.

andreyu ★★★★★
()
Ответ на: комментарий от devinull

> А чём прикол? Так и долэно быть. Это выделение одного объекта типа int, инициализированного значением arrSize. Компилер тут безсилен.

Прикол в том, что человеку сразу видно, что это бред. Много ли раз вы размещали одинокий инт в куче?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Бывало и такое. В детстве, когда баловался с winapi, приходилось и не такое вытворять ) Но то по зелени было )

devinull ★★
()
Ответ на: комментарий от vnovouhov

Как тут правильно заметил один товаришь, res = new int(arrSize) это выделение одного инта и вызов у него конструктор от arrSize

И еще. При использовании посфиксной вормы все равно компилятор без оптимизации будет вынужден сохранить старое значение, пусть и тривиально, переменое. А это растраты

namezys ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.