Функция считывает матрицу из файла в динамический массив, сразу же выводит её и отправляет в main, предварительно узнав размеры этой матрицы из другой функции (плюс разные проверки существования файла и прочее, но не суть). Сама программа и данная функция работают безупречно, но анализ кода в Visual Studio выдаёт вот такое вот предупреждение:
Предупреждение C6386. Переполнение буфера при записи в “matrix”:
доступный для записи объем равен “strings*sizeof(int *)” байт,
однако записать можно только “16” байт.
Так вот, мне интересно почему он на это ругается и стоит ли обращать внимание?
P.S. Анализом кода занялся совсем недавно, к примеру узнал про нулевой указатель и в функции уже это дело подправил.
Сам код:
int **GetMatrixFile(const char filename[], const int strings, const int columns)
{
FILE *file;
int **matrix;
fopen_s(&file, filename, "r");
if (file != NULL)
{
printf("Матрица %c(%d x %d):n",
filename[0], strings, columns);
matrix = (int**)malloc(strings * sizeof(int*));
if (matrix != NULL)
{
for (int i = 0; i < strings; ++i)
{
printf("|");
matrix[i] = (int*)malloc(columns * sizeof(int));
if (matrix[i] != NULL)
{
for (int j = 0; j < columns; ++j)
{
fscanf_s(file, "%d", &matrix[i][j]);
printf("%3d ", matrix[i][j]);
}
}
else exit(EXIT_FAILURE);
printf("|n");
}
}
else exit(EXIT_FAILURE);
fclose(file);
}
else exit(EXIT_FAILURE);
return matrix;
}
savvakhrenkov 0 / 0 / 0 Регистрация: 19.02.2022 Сообщений: 2 |
||||
1 |
||||
19.02.2022, 21:30. Показов 1518. Ответов 5 Метки нет (Все метки)
Необходимо задать динамический массив структур из номера строки и указателя на строку и по запросу пользователя инвертировать одну из строк. При компиляции на моменте с инвертированием строки номер “a” компилятор VS Studio 2019 выдает предупреждения C6385 и C6386 (строки 51 и 52 соответственно). Никак не могу понять, отчего так. Код прилагаю.
0 |
685 / 392 / 200 Регистрация: 19.12.2016 Сообщений: 1,586 |
|
19.02.2022, 21:48 |
2 |
А у вас
0 |
фрилансер 4759 / 4361 / 924 Регистрация: 11.10.2019 Сообщений: 11,451 |
|
19.02.2022, 21:56 |
3 |
выдает предупреждения текст предупреждений то какой ? Добавлено через 2 минуты
0 |
0 / 0 / 0 Регистрация: 19.02.2022 Сообщений: 2 |
|
19.02.2022, 22:06 [ТС] |
4 |
C6385 Чтение недопустимых данных из “Array[invert].str”: доступный для чтения объем равен “size*1” байт, однако считать можно только “2” байт. Добавлено через 4 минуты
это учебное задание на динамические массивы или боевой код Учебное задание Добавлено через 2 минуты
А у вас #include <cstring> подключен? Подключена библиотека . На мой VS плюется и не находит.
0 |
685 / 392 / 200 Регистрация: 19.12.2016 Сообщений: 1,586 |
|
19.02.2022, 22:10 |
5 |
не находит. Как тогда strlen может работать?
0 |
24 / 57 / 31 Регистрация: 06.08.2020 Сообщений: 209 |
|
19.02.2022, 22:21 |
6 |
В VS нормально работает с #include<string> хотя да, по идее strlen это сишный прикол. А предупреждения мне думается это студию смущает некоторая непонятность переменной invert. Но на работу это не влияет.
0 |
Я пытаюсь реализовать сортировку слиянием в C, когда натолкнулся на что-то интересное, поднятое [Analyze -> Run Code Analysis] в Visual Studio 2015.
Код выглядит следующим образом:
void MergeSort_r(int A[], int n)
{
// A = {1, 3, 2}
// n = 3
int rightCount;
int* R;
if ( n < 2 ) return;
// version 1: rightCount = 2
rightCount = n - (n/2);
// version 2: rightCount = 2
rightCount = n - 1;
R = ( int* ) malloc( rightCount * sizeof( int ) );
if ( R ) {
for ( int i = 0; i < rightCount; i++ ) {
R[i] = A[i];
}
free( R );
}
}
Хотя обе версии rightCount по существу оцениваются как 2, в первой версии я получаю предупреждение:
«Переполнение буфера при записи в ‘R’: размер записи равен ‘(unsigned int) rightCount * sizeof (int)’ байтов, но может быть записано 8 байтов.»
Есть идеи, почему это так? Будем рады услышать ваши ответы.
2
Решение
Набор инструментов для анализа кода в Visual C ++ не всегда предлагает лучшие предупреждения. Он пытается дать вам лучший набор предупреждений, чтобы исправить некоторые потенциальные проблемы / ошибки, которые могут появиться во время выполнения. У вас есть несколько вариантов:
- Отключите данное предупреждение вокруг кода, используя
#pragma
директивы. - Используйте конструкции C ++:
new
,make_unique
и т.п. - (Не рекомендуется) это полностью игнорировать предупреждение и двигаться дальше.
В идеале вы всегда должны использовать новые примитивы smart pointers, такие как unique_ptr
, shared_ptr
и т.д. Они не только выделяют память для вас, но и освобождают от любого исключения, выброшенного в стек вызовов. Вам не нужно вводить *
полностью!
auto buffer = make_unique<int[]>(10); // 10 integers
3
Другие решения
Ваш код в порядке, и инструменты (особенно анализаторы) имеют свои недостатки — иногда они генерируют ложные срабатывания. Это один из них. Кстати, я проверил ваш код на MSVS2015, и он не дает мне никаких предупреждений.
3
Visual Studio 2019 по умолчанию начала показывать предупреждения анализа кода в виде зеленых волнистых линий в редакторе. Это может быть чрезвычайно полезно для студентов, изучающих программирование на C, потому что они выявляют классические ошибки, такие как отключение доступа к одному массиву.
К сожалению, ложные срабатывания могут полностью испортить процесс обучения, и я боюсь, что мне придется попросить учеников отключить эту функцию, чтобы они не беспокоились о несуществующих проблемах.
Этот короткий фрагмент не вызывает никаких предупреждений:
#include <stdlib.h>
int main(void)
{
size_t n = 6;
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return 1;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
free(v);
return 0;
}
К сожалению, если вы переместите выделение в функции, например:
#include <stdlib.h>
int *test(size_t n)
{
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return NULL;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
return v;
}
int main(void)
{
size_t n = 6;
int *v = test(n);
free(v);
return 0;
}
Вы получите warning C6386: Buffer overrun while writing to 'v': the writable size is 'n*sizeof(int)' bytes, but '8' bytes might be written.
Даже читая Stack Overflow, я не понимаю, откуда взялся '8'
, но, что более важно, почему он не распознает, что i
никогда не выйдет за пределы допустимого диапазона.
Возникает вопрос: есть ли способ написать этот тип кода таким образом, чтобы не было предупреждения?
Я знаю, что могу перейти к Tools > Options > Text Editor > C/C++ > Experimental > Code Analysis
и установить Disable Code Analysis Squiggles
на True
или использовать #pragma warning(disable:6386)
, но я бы предпочел этого избежать и, конечно, не предлагаю своим ученикам последнее.
2 ответа
Лучший ответ
Я действительно хочу поблагодарить всех за их вклад и согласен с тем, что это ошибка анализатора кода (если посмотреть на веб-сайты Microsoft, два года назад он был” закрыт – более низкий приоритет “…).
Уловка Адриана Моула max(n, 0)
указывает способ справиться с предупреждением в коде, то есть проверять, что n
больше нуля. Забавно то, что вы все еще можете использовать этот ноль для того, что предполагалось использовать n
. Хотя эту идею можно использовать для опытных программистов (что, вероятно, отключило бы предупреждение), как указывает Джон Боллинджер, она не для студентов.
Поэтому, сказав студентам, что это ошибка и как отключить волнистые линии анализа кода или отключить предупреждение, я бы пошел с
int *test(size_t n)
{
if (n == 0) {
return NULL;
}
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return NULL;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
return v;
}
Это также можно интерпретировать как: не разрешать размещение 0 элементов.
0
Costantino Grana
7 Ноя 2020 в 04:38
Visual Studio 2019 started showing Code Analysis warnings as in-editor green squiggles by default. These may be extremely useful for students learning C programming, because they catch classical mistakes, such as off by one array accesses.
Unfortunately false positives may completely ruin the learning experience and I fear that I will have to ask the students to disable the feature in order to avoid having them worry on non existing problems.
This short snippet doesn’t cause any warning:
#include <stdlib.h>
int main(void)
{
size_t n = 6;
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return 1;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
free(v);
return 0;
}
Unfortunately, if you move the allocation in a function, like this:
#include <stdlib.h>
int *test(size_t n)
{
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return NULL;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
return v;
}
int main(void)
{
size_t n = 6;
int *v = test(n);
free(v);
return 0;
}
you get a warning C6386: Buffer overrun while writing to 'v': the writable size is 'n*sizeof(int)' bytes, but '8' bytes might be written.
Even reading on Stack Overflow, I don’t get where the '8'
comes from, but, more importantly, why it fails to recognize that i
will never be out of range.
So the question is: is there a way to write this type of code in a way that will not generate the warning?
I know that I can go to Tools > Options > Text Editor > C/C++ > Experimental > Code Analysis
and set Disable Code Analysis Squiggles
to True
, or use a #pragma warning(disable:6386)
, but I’d rather avoid it, and certainly avoid suggesting my students the latter.