Неверное чтение размера 8, Неверное чтение размера 8 (Valgrind)

Этим вечером я несколько часов играл со следующим кодом, и я просто почесал им голову.

Я продолжаю получать «Недопустимая запись размера 8» и «Недопустимое чтение размера 8» при использовании функции для заполнения массива из stdin.

Буду признателен за любую помощь … Я знаю, что в переполнении стека существует множество таких ошибок, но большинство из них уникальны для данной ситуации.

void RawScore(unsigned int rawScoreCount, unsigned int numStudents, student studentInfo[],
unsigned int projectCount, double rawScores[], double scores[], double weights[])
{
int id;

for (int i = 0; i < rawScoreCount; i++)
{
std::cin >> id;

for (int j = 0; j < numStudents; j++)
{
if (id == studentInfo[j].id)
{
for (int k = 0; k < projectCount; k++)
{
std::cin >> rawScores[k];
studentInfo[j].score += rawScores[k]/scores[k] * weights[k];
}
}
}
std::cin.ignore(10000, '\n');
}
}

Ошибка от Memcheck ниже:

==5793== Memcheck, a memory error detector
==5793== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5793== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==5793== Command: a.out.app
==5793==
==5793== Invalid write of size 8
==5793==    at 0x40E54DB: std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > std::__1::num_get<char, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > >::__do_get_floating_point<double>(std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, unsigned int&, double&) const (in /usr/lib/i386-linux-gnu/libc++.so.1.0)
==5793==    by 0x40E517E: std::__1::num_get<char, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > >::do_get(std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, unsigned int&, double&) const (in /usr/lib/i386-linux-gnu/libc++.so.1.0)
==5793==    by 0x804D0FA: std::__1::basic_istream<char, std::__1::char_traits<char> >::operator>>(double&) (locale:771)
==5793==    by 0x804CECC: RawScore(unsigned int, unsigned int, student*, unsigned int, double*, double*, double*) (input.cpp:44)
==5793==    by 0x804EE6A: main (main.cpp:35)
==5793==  Address 0x445c388 is 0 bytes after a block of size 40 alloc'd
==5793==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5793==    by 0x40BA709: operator new(unsigned int) (in /usr/lib/i386-linux-gnu/libc++.so.1.0)
==5793==    by 0x804EE26: main (main.cpp:32)
==5793==
==5793== Invalid read of size 8
==5793==    at 0x804CED3: RawScore(unsigned int, unsigned int, student*, unsigned int, double*, double*, double*) (input.cpp:49)
==5793==    by 0x804EE6A: main (main.cpp:35)
==5793==  Address 0x445c388 is 0 bytes after a block of size 40 alloc'd
==5793==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5793==    by 0x40BA709: operator new(unsigned int) (in /usr/lib/i386-linux-gnu/libc++.so.1.0)
==5793==    by 0x804EE26: main (main.cpp:32)
==5793==
....... output of program here ......
==5793==
==5793== HEAP SUMMARY:
==5793==     in use at exit: 0 bytes in 0 blocks
==5793==   total heap usage: 9 allocs, 9 frees, 476 bytes allocated
==5793==
==5793== All heap blocks were freed -- no leaks are possible
==5793==
==5793== For counts of detected and suppressed errors, rerun with: -v
==5793== ERROR SUMMARY: 20 errors from 2 contexts (suppressed: 0 from 0)

Я сузил проблему до следующих двух строк: 10 ошибок при записи и 10 при чтении:

std::cin >> rawScores[k];
studentInfo[j].score += rawScores[k]/scores[k] * weights[k];

Любое понимание будет оценено!

0

Решение

std::cin >> rawScores[k];
studentInfo[j].score += rawScores[k]/scores[k] * weights[k];

Из вашей вышеуказанной программы j а также k зависит от ввода пользователя и, следовательно, их значения могут выходить за пределы фактического массива studentInfo rawScores индекс.

Ваша программа должна иметь логику, чтобы ваша программа не имела доступа к границам массива.

Вы можете контролировать свою программу

$ valgrind --tool=memcheck --db-attach=yes ./a.out

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

https://stackoverflow.com/a/22658693/2724703

1

Другие решения

Вы правильно распределяете rawScores?

Вы также должны убедиться, что projectCount меньше размера rawScores

1

  1. Проверьте, достаточно ли памяти выделено для массивов [rawScores,
    очки, веса, studentInfo], прежде чем перейти к этой функции.
  2. проверьте пользовательский ввод, должен быть в диапазоне массивов.

это решило бы вашу проблему

0

Переполнения границ массива коварны. В C ++, если вы не повредите то, что вам небезразлично, вы, возможно, никогда не узнаете, что что-то нарушаете … За исключением того, что некоторые из ваших значений могут быть не совсем правильными.
(Это «ошибка», лежащая в основе многих вирусных атак — использование плохо написанных программ, которые делают предположения о размерах буфера / массива).

Допустим, у вас есть что-то вроде:

   char buffer[50];
char author[] = "My Name";

cout << author;
cin >> buffer;

Если я наберу 20-символьную строку ввода, без вреда, без фола.

Если я введу 55-символьную строку ввода, «Мое имя» будет частично перезаписано, что никто не заметит, если я не попытаюсь перепечатать автора. Что не может произойти, пока много (много) заявлений позже. Когда вы видите автора, возможно, это выглядит как «1234ame», и вы будете спрашивать «откуда это взялось?

Хуже того, если я введу строку ввода из 70 символов, я откажу автору, и все, что будет после него, возможно, блок управления памятью, буфер ввода-вывода и т. Д., И, возможно, это будет «заметно» (или нет) ,

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

Как говорил ранее Рупеш — внимательно относитесь к своим массивам, как к выделению, так и к заполнению.

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

0
По вопросам рекламы [email protected]