Foreversoft.ru

IT Справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

C delete ошибка

C++ New/Delete Ошибка?

В настоящее время я внедряю сетку простых чисел в C++, и я разработал код таким образом, чтобы я мог контролировать размер сетки (через целочисленный литерал в основной функции), но я получаю некоторые нечетные ошибки во всем. Я не использовал C++ в течение нескольких лет, но я помню, что использовал операторы new и delete для управления памятью heap.

Моя проблема является своего рода следующим образом.

Программа работает для некоторых размеров сита, но не для других, и эффект не является строго линейным. Например, если я делаю сито размером 10 000, программа работает нормально, но если я делаю его размером 1000, программа падает с довольно загадочным (для моего опыта) сообщением, которое всегда приводит меня к страницам об ошибках утверждения C malloc (через google). Кроме того, программа отлично работает для 10 000 с инструкциями delete peppered in, BUT рухнет, если я запущу через valgrind с другим бесполезным (для меня) сообщением. В результате я даже не могу отладить эту чертову вещь самостоятельно DX

Какие-нибудь мудрые слова?

В частности, почему программа аварийно завершает работу с меньшим входом? Теоретически, это было бы менее вероятно, чтобы вызвать ошибки heap, не так ли? Кроме того, почему valgrind не может запустить программу, пока она может работать сама по себе? Я подозреваю, что (опять же) это имеет какое-то отношение к ошибочному или уродливому использованию операторов new/delete, но я не совсем уверен. Часть (о valgrind ), которая особенно озадачивает меня, заключается в том, что она упоминает в ошибке, что я использую оператор new на unsigned long , который, насколько я могу судить, не является тем, что я делаю (по крайней мере, не специально). Я предполагаю, что это какая-то деталь, связанная с компилятором, с которой я не знаком, но опять же я не совсем уверен.

Код (с оператором delete; работает с размером 10,000, но не через valgrind ):

valgrind ошибка для выше:

Ошибка при изменении размера на 1000:

EDIT:

Я очень благодарен за всю (фактическую) помощь! Благодаря ответам ниже, программа теперь будет работать для большинства входов (не слишком больших, конечно), но я все еще получаю ошибку Valgrind. Я не очень против этого , но мне любопытно понять, что происходит. Я попытался предложить ниже изменить механизм выбора случайного простого числа на (((long) rand_int1) % prime_list_size); , а не на (((long) rand_int1) * prime_list_size)/RAND_MAX , но у меня не было заметных результатов на стороне Valgrind. Я все еще не могу точно сказать, откуда берется недопустимая запись heap. Я изменю код, чтобы увидеть, если это мои удаления, которые вызывают и будет отчитываться.

2 Ответа

выполняет ли назначение sieve[b*a] BEFORE проверку, если b*a . Это позволяет назначить элемент за конец массива. Это неопределенное поведение на последней итерации этого цикла.

Вам было бы лучше использовать std::vector [отмечая , что у него есть некоторые ограничения, которых нет у других векторов] или std::bitset , а не возиться вручную с операторами new и delete . Имейте в виду, что все еще необходимо убедиться, что ваш код не падает с конца стандартных контейнеров.

Я вижу две проблемы в вашем коде.

Первый из них здесь:

Это не может предотвратить запись за предел size , потому что проверка происходит после присвоения ‘ sieve[b*a] = false;

Другая проблема, которую я вижу, здесь:

long rand_num1 = (((long) rand_int1) * prime_list_size)/RAND_MAX;

long rand_num2 = (((long) rand_int2) * prime_list_size)/RAND_MAX;

Термин в умножении может привести к переполнению. Я думаю, вы хотите получить случайный индекс меньше, чем size ? Вы могли бы просто сделать это таким образом:

Конечно, это не даст идеального равномерного распределения, но это будет работать. Для лучшего распределения взгляните на число случайных генераторов библиотеки std, а также на его vector , что является очень хорошим инструментом для того, что вы делаете.

Похожие вопросы:

Я узнал кое-что о перегрузке new/delete в Primer C++ Primer》.Но мне очень любопытно :поскольку по умолчанию new / delete настолько хорош, когда я должен их перегружать?

Поэтому я новичок, пытающийся справиться с новым оператором. Что случилось с моим деструктором? >
разница между new[ ] / delete [ ] и new / delete в C++

У меня есть очень быстрый вопрос: в чем разница между new[ ] / delete [ ] vs new / delete в C++, когда речь заходит о динамической памяти? Разве new[ ] / delete [ ] не принадлежат динамической.

Я пытаюсь подключиться к new / delete в C++ Когда дело доходит до malloc / free, это просто: просто прочитайте его: http://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html Но, как.

Вызывает ли оператор c++ оператор new[]/delete[] (не мой) оператор new/delete? После того, как Я заменил operator new и operator delete своей собственной имплементацией, следующий код вызовет их.

Перегрузка операторов new и delete может работать или не работать при компиляции с использованием разных компиляторов и разных стандартов c++. Это нормальное поведение? Я использовал следующий код.

Я добавления функциональности в существующие приложения написаны в основном на Cocoa цель-C. Я должен использовать существующий класс c++ в классе, который я пишу, поэтому новый класс является.

Читать еще:  Attrib ошибка в формате параметра

Что такое эквивалент new / delete из C++ в C? Или то же самое в C/C++? году

Я просто вижу некоторые объявления в libstdc++ — v3, но не могу найти определения. Ли new и delete просто инкапсулировать malloc и free ? Где я могу найти определения new и delete ? И почему я не.

Как закодировать мою программу, чтобы иметь гибкость для получения пользовательского распределителя заранее? Я закодировал некоторые распределители, но не уверен, действительно ли мне это.

delete, new[] в C++ и городские легенды об их сочетании

Если в коде на C++ был создан массив объектов с помощью «new[]», удалять этот массив нужно с помощью «delete[]» и ни в коем случае не с помощью «delete» (без скобок). Разумный вопрос: а не то что?

На этот вопрос можно получить широчайший спектр неразумных ответов. Например, «будет удален только первый объект, остальные утекут» или «будет вызван деструктор только первого объекта». Следующие за этим «объяснения» не выдерживают обычно никакой серьезной критики.

В соответствии со Стандартом C++, в этой ситуации поведение не определено. Все предположения – не более чем популярные городские легенды. Разберем подробно, почему.

Нам понадобится хитрый план с примером, который бы ставил в тупик сторонников городских легенд. Вот такой безобидный будет ок:

Здесь объект в массиве всего один. Если верить любой из двух легенд выше, «все будет хорошо» – утекать нечему и некуда, деструкторов будет вызвано ровно сколько нужно.

Идем на codepad.org, вставляем код в форму, получаем выдачу:

MEMORY WHAT. Что это было?

Здесь хотя бы с виду все хорошо. Что происходит? Почему так происходит? Почему поведение с виду разное?

Причина в том, что происходит внутри.

Когда в коде встречается «new Type[count]», программа обязана выделить память объема, достаточного для хранения указанного числа объектов. Для этого она использует функцию «operator new[]()». Эта функция выделяет память – обычно внутри просто вызов malloc() и проверка возвращаемого значения (при необходимости – вызов new_handler() и выброс исключения). Затем в выделенной памяти конструируются объекты – вызывается нужное число конструкторов. Результатом «new Type[count]» является адрес первого элемента массива.

Когда в коде встречается «delete[] pointer», программа должна разрушить все объекты в массиве, вызвав для них деструкторы. Для этого (и только для этого) ей нужно знать число элементов.

Важный момент: в конструкции «new Type[count]» число элементов было указано явно, а «delete[]» получает только адрес первого элемента.

Откуда программа узнает число элементов? Раз у нее есть только адрес первого элемента, она должна вычислить длину массива на основании одного этого адреса. Как это делается, зависит от реализации, обычно используется следующий способ.

При выполнении «new Type[count]» программа выделяет памяти столько, чтобы в нее поместились не только объекты, но и беззнаковое целое (обычно типа size_t), обозначающее число объектов. В начало выделенной области пишется это число, дальше размещаются объекты. Компилятор при компиляции «new Type[count]» вставляет в программу код, который реализует эти свистелки.

Итак, при выполнении «new Type[count]» программа выделяет чуть больше памяти, записывает число элементов в начало выделенного блока памяти, вызывает конструкторы и возвращает вызывающему коду адрес первого элемента. Адрес первого элемента будет отличаться от адреса, который возвратила функция выделения памяти «operator new[]()».

При выполнении «delete[]» программа берет адрес первого элемента, переданный в «delete[]», определяет адрес начала блока (вычитая ровно столько же, сколько было прибавлено при выполнении «new[]»), читает число элементов из начала блока, вызывает нужное число деструкторов, затем – вызывает функцию «operator delete[]()», передав ей адрес начала блока.

В обоих случаях вызывающий код работает не с тем адресом, который был возвращен функцией выделения памяти и позже – передан функции освобождения памяти.

Теперь вернемся к первому примеру. Когда выполняется «delete» (без скобок), вызывающий код понятия не имеет, что нужно проиграть последовательность со смещением адреса. Скорее всего, он вызывает деструктор единственного объекта, затем передает в функцию «operator delete()» адрес, который отличается от ранее возвращенного функцией «operator new[]()».

Что должно произойти? В этой реализации программа аварийно завершается. Поскольку Стандарт говорит, что поведение не определено, это допустимо.

Для сравнения, программа на Visual C++ 9 по умолчанию исходит сообщениями об ошибках в отладочной версии, но вроде бы нормально отрабатывает (по крайней мере, функция _heapchk() возвращает код _HEAP_OK, _CrtDumpMemoryLeaks() не выдает никаких сообщений). Это тоже допустимо.

Почему во втором примере поведение другое? Скорее всего, компилятор учел, что у типа char тривиальный деструктор, т.е. не нужно ничего делать для разрушения объектов, а достаточно просто освободить память, поэтому и число элементов хранить не нужно, а значит, можно сразу вернуть вызывающему коду тот же адрес, который вернула функция «operator new[]()». Никаких смещений адреса – точно так же, как и при вызове «new» (без скобок). Такое поведение компилятора полностью соответствует Стандарту.

Читать еще:  Iherb ошибка 1015

Чего-то не хватает…

Вы уже заметили, что выше по тексту встречаются функции выделения и освобождения памяти то с квадратными скобками, то без? Это не опечатки – это две разные пары функций, они могут быть реализованы совершенно по-разному. Даже когда компилятор пытается сэкономить, он всегда вызывает функцию «operator new[]()», когда видит в коде «new Type[count]», и всегда вызывает функцию «operator new()», когда видит в коде «new Type».

Обычно реализации функций «operator new()» и «operator new[]()» одинаковы (обе вызывают malloc()), но их можно заменить – определить свои, причем можно заменить как одну пару, так и обе, также можно заменять эти функции по отдельности для любого выбранного класса. Стандарт позволяет это делать сколько угодно (естественно, нужно адекватно заменить парную функцию освобождения памяти).

Это дает богатые возможности для неопределенного поведения. Если ваш код приводит к тому, что память освобождается «не той» функцией, это может приводить к любым последствиям, в частности, к повреждению кучи, порче памяти или немедленному аварийному завершению программы. В первом примере реализация функции «operator delete()» не смогла распорядиться переданным ей адресом и программа аварийно завершилась.

Самая приятная часть этого рассказа – вы никогда не сможете утверждать, что использование «delete» вместо «delete[]» (и наоборот – тоже) приводит к какому-то конкретному результату. Стандарт говорит, что поведение не определено. Даже полностью соответствующий Стандарту компилятор не обязан выдать вам программу с каким-либо адекватным поведением. Поведение программы, на которое вы будете ссылаться в комментариях и спорах, является только наблюдаемым – внутри может происходить все что угодно. Вы только констатируете наблюдаемое вами поведение.

Во втором примере с виду все хорошо… на этой реализации. На другой реализации функции «operator new()» и «operator new[]()» могут быть, например, реализованы на разных кучах (Windows позволяет создавать более одной кучи на процесс). Что произойдет при попытке возвратить блок «не в ту» кучу?

Кстати, рассчитывая на какое-то конкретное поведение в этой ситуации, вы автоматически получаете непереносимый код. Даже если на текущей реализации «все работает», при переходе на другой компилятор, при смене версии компилятора или даже при обновлении C++ runtime вы можете быть крайне неприятно удивлены.

Как быть? Смириться, не путать «delete» и «delete[]» и самое главное – не тратить зря время на «правдоподобные» объяснения того, что якобы произойдет, если вы их перепутаете. Пока вы будете спорить, другие разработчики будут делать что-то полезное, а для вас будет расти вероятность заслужить премию Дарвина.

Дмитрий Мещеряков
Департамент продуктов для разработчиков

Ошибка: использование удаленной функции

70 shuttle87 [2011-05-11 18:25:00]

Я работал над некоторым кодом на С++, который написал друг, и я получаю следующую ошибку, которую я никогда раньше не видел при компиляции с gcc4.6:

Изменить: это происходит из части кода, использующего boost MSM: Boost Webpage

Edit2: Нет = delete() , используемого в любом месте исходного кода.

Вообще говоря, что означает эта ошибка? Что я должен искать, когда возникает этот тип ошибок?

c++ gcc c++11 g++ deleted-functions

6 ответов

116 Решение Jerry Coffin [2011-05-11 18:35:00]

Я не думаю, что другие ответы, говорящие о синтаксисе =deleted; , верны. В сообщении об ошибке четко указано, что конструктор по умолчанию был удален неявно. Он даже говорит, почему: класс содержит нестатические переменные const, которые не будут инициализированы по умолчанию ctor.

Так как X::x есть const , он должен быть инициализирован, но по умолчанию ctor обычно не инициализирует его (поскольку это тип POD). Поэтому, чтобы получить значение по умолчанию ctor, вам нужно определить его самостоятельно (и он должен инициализировать x ). Вы можете получить такую ​​же ситуацию с членом, что и ссылка:

Вероятно, стоит отметить, что оба из них также отключат неявное создание оператора присваивания и по той же причине. Оператор неявного присваивания обычно выполняет назначение членов, но в этих случаях он не может, поскольку член является тем, который не может быть назначен. Чтобы выполнить работу задания, вам нужно написать свой собственный оператор присваивания.

Вот почему член const обычно должен быть статичным — если вы выполняете задание, вы не можете назначить константный член в любом случае. В типичном случае все ваши экземпляры будут иметь одинаковое значение, чтобы они могли совместно использовать доступ к одной переменной вместо того, чтобы иметь много копий переменной, которые будут иметь одинаковое значение.

Можно, конечно, создать экземпляры с разными значениями, хотя вы (например) передаете значение при создании объекта, поэтому два разных объекта могут иметь два разных значения. Если, однако, вы пытаетесь сделать что-то вроде их замены, член const сохранит свое первоначальное значение вместо того, чтобы быть замененным.

6 Alok Save [2011-05-11 18:28:00]

Вы используете функцию, которая помечена как deleted .
Например:

The = delete — это новая функция С++ 0x. Это означает, что компилятор должен немедленно прекратить компиляцию и жаловаться «эта функция будет удалена» после использования пользователем такой функции.

Если вы видите эту ошибку, вы должны проверить декларацию функции для =delete .

Читать еще:  Код ошибки ex0

Чтобы узнать больше об этой новой функции, введенной в С++ 0x, отметьте этот.

gcc 4.6 поддерживает новую функцию удаленных функций, где вы можете написать

чтобы отключить конструктор по умолчанию.

Здесь компилятор явно видел, что конструктор по умолчанию не может быть сгенерирован, а =delete ‘d это для вас.

1 jarmond [2011-05-11 18:30:00]

В текущем стандарте С++ 0x вы можете явно отключить конструкторы по умолчанию с синтаксисом delete, например.

Gcc 4.6 — первая версия, поддерживающая этот синтаксис, поэтому, возможно, это проблема.

Удаляем обновление, вызывающее ошибку c0000145

Microsoft в очередной раз радует мелкими пакостями владельцев 64-разрядных нелицензионных систем Windows. Но уж если установили пиратку, значит взяли всю ответственность за последствия на себя, а значит и лечиться будем сами.

Мы специально несколько раз устанавливали кривое обновление KB3045999 для вызова подобной ошибки и удалял разными способами найденными в интернете. И поскольку информация достойна внимания, не побоюсь повториться. Проверено, оба описанных способа рабочие.

В обоих случаях вам понадобится ERD commander для вашей Windows (подробнее в конце статьи), в первом случае для отката системы, во втором для вызова командной строки. Где скачать ERD? Да никаких проблем: Интернет, торренты и варезники просто завалены данным софтом, пользуемся поиском Яндекса.

Загружаемся с диска или флешки с записанным Erd Commander или с загрузочного диска Windows с интегрированным msdart.

После сканирования установленных операционных систем выделяем нужную, если их несколько, и жмем далее.

Лечение c0000145 application error методом отката системы

В параметрах восстановления системы выбираем второй пункт Восстановление системы и откатываем до предыдущей или более ранней точки восстановления. Если в процессе восстановления возникает ошибка (к сожалению бывает и такое) то выбираем первый пункт Восстановление запуска. Немного ждем пока система сканируется, потом перезагружаем компьютер.

Лечение c0000145 application error из командной строки

Если у вас оказалось отключенным создание точек восстановления и предыдущий метод не сработал, снова загружаемся с диска, но для начала рекомендую посмотреть не изменилась ли буква системного диска.

Переходим вниз окна и жмем Microsoft Diagnostics and Recovery Toolset.

И с помощью проводника смотрим на каком диске установлен Windows.

Теперь закрываем второе окошко, а в первом (которое видим в самом начале) выбираем пункт Командная строка.

В командной строке уже будет запись наподобие x:Sources> (зависит от загрузочного софта), не обращаем внимания, продолжаем писать в этой же строке: DISM /Image: C: /Get-Packages где вместо С пишем вашу букву системного раздела диска. В моем примере системным стал раздел D.

Получаем x:Sources>DISM /Image:C: /Get-Packages и жмем Enter.

Ждем несколько секунд и в длинном списке обновлений находим нужное. Что бы не писать много лишних букв, выделяем часть строки с названием обновления и жмем Ctrl+C (копируем в буфер обмена).

Теперь пишем (придется писать ручками :)) DISM /Image:C: /Remove-Package /PackageName: и здесь правой кнопкой мыши вставляем скопированное. Если не получилось скопировать, не беда, напишем руками, только внимательнее плиз.

DISM /Image:C: /Remove-Package /PackageName:Package_for_KB3045999

6.1.1.1 и жмем Enter.

Через секунду — другую видим результат 100%, перезагружаемся, меняем автоматическую установку обновлений на ручную, и ждём когда вновь нам предложат установить это обновление, скрываем его к едрени-фени

Если в процессе лечения с0000145 из командной строки вы получаете какие то ошибки, то повторяем процедуру внимательнее.

Самые частые ошибки

Неправильное написание буквы диска, написали не ту букву диска на котором установлена система, вместо нижнего подчеркивания _ написали дефис , пропустили двоеточие, сделали запись без пробелов там где нужно. И да, тильда

набирается клавишами Shift+Ё (клавиша слева от клавиши «1» во втором ряду) в английской раскладке.

P. S. Те же самые действия проводим и с необязательным обновлением KB3022345 вышедшим в мае. Еще KB3068708, 3060716 и 3071756 от 25.08.2015. Необязательное обновление KB3080149, KB3088195

P. P. S. Для копирования и вставки можете использовать меню (квадратик в левом верхнем углу), выделяем нужное, жмем на меню — изменить — копировать и изменить — вставить.

Кстати говоря, чтобы самому не заниматься установкой и удалением обновлений, чтобы иметь возможность контролировать работоспособность устройств в вашем офисе, разумно заключить договор на услуги ит аутсорсинга. В этом случае приходящий системный администратор сможет просто прийти и, выслушав ваши проблемы и пожелания, устранить ошибки. Такое абонентское обслуживание поможет сэкономить вам время, а значит и деньги. Ведь тогда простои в работе офиса и связанные с этим материальные издержки можно исключить.

Быстрый откат системы

Если у вас отсутствует диск с ERD commander: при появлении экрана смерти с ошибкой, жмем и удерживаем кнопку включения до отключения пк, затем снова включаем. Вам будет предложено 2 варианта: восстановление системы и обычная загрузка, выбираем восстановление. Далее жмем восстановить, через пару минут получаем сообщение что восстановить не удалось или ошибок не найдено — тут жмем на нижнюю строчку дополнительные параметры восстановления и получаем нужное меню ERD commander.

Ссылка на основную публикацию
Adblock
detector