C ошибка c6386

It is just a warning but it is giving good advice. What if the file contains more than num items? The warning is telling you that should make sure you don’t write past the end of the array. Specifically:

This warning indicates that the writable extent of the specified buffer might be smaller than the index used to write to it. This can cause buffer overrun. [msdn]

This code does not produce the warning (VS2019):

int x, y;
while (i < num && (file >> x >> y)) {
    points[i].x = x;
    points[i].y = y;
    i++;
}

There is still more error checking to add. What if file >> num; fails? What if num is negative ? What if points = new point[num]; fails (returns nullptr)?


Updated with full error checking:

struct point {
    int x, y;
};

void main()
{
    ifstream file("C:\Users\Den\Desktop\file.txt");
    if (!file) {
        cerr << "No file foundn";
        exit(-1);
    }

    int num;
    if (!(file >> num) || num <= 0) {
        cerr << "invalid numn";
        exit(-1);
    }
    point *points = new point[num];
    if (!points) {
        cerr << "new failedn";
        exit(-1);
    }
    int num_items = 0;
    while (num_items < num && file >> points[num_items].x >> points[num_items].y) {
        num_items++;
    }
    // Do some work here
    delete [] points;
}

In the future, consider using std::vector over raw array.

savvakhrenkov

0 / 0 / 0

Регистрация: 19.02.2022

Сообщений: 2

1

19.02.2022, 21:30. Показов 1559. Ответов 5

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Необходимо задать динамический массив структур из номера строки и указателя на строку и по запросу пользователя инвертировать одну из строк. При компиляции на моменте с инвертированием строки номер «a» компилятор VS Studio 2019 выдает предупреждения C6385 и C6386 (строки 51 и 52 соответственно). Никак не могу понять, отчего так. Код прилагаю.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <string>
 
struct recs {
    int k;
    char* str;
};
 
int main()
{
    int num;
    std::cout << "Enter num" << std::endl;
    std::cin >> num;
    std::cin.get();
    
    recs *Array = new recs[num]; //массив структур
    int *stringlength = new int[num]; //массив длин строк соответвующих элементов структур (для удобства)
    
    for (int i = 0; i < num; i++)
    {
        Array[i].k = i;
        std::string string;
        std::cout << "Enter string " << i+1 << std::endl;
        std::getline(std::cin, string);
        int size = string.length() + 1;
        stringlength[i] = size-1;
        
        Array[i].str = new char[size]; //динамический массив для хранения i-й строки
        for (int j = 0; j < size; j++)
        {
            Array[i].str[j] = string[j];
        }
    }
 
    try
    {
        int a;
        std::cout << "Enter the number of string to invert" << std::endl;
        std::cin >> a;
        int invert = a - 1;
        if (a > num)
            throw "There is no such string";
        if (a < 1)
            throw "There is no such string";
        
        int len = strlen(Array[invert].str);
        int k = len - 1;
        for (int i = 0; i < (int)((len-1) / 2); i++)
        {
            char t;
            t = Array[invert].str[i];
            Array[invert].str[i] = Array[invert].str[k];
            Array[invert].str[k] = t;
            k = k - 1;
        }
    }
    catch(const char*)
    {
        std::cout << "Error: there is no such string";
        delete[] Array;
        delete[] stringlength;
        Array = 0;
        stringlength = 0;
        exit(0);
    }
    std::cout << "" << std::endl;
 
    for (int z = 0; z < num; z++)
    {
        std::cout << Array[z].k+1 << " || " << Array[z].str << std::endl; 
        delete[] Array[z].str; //возвращение памяти системе
    }
    delete[] Array; 
    delete[] stringlength;
    Array = 0;
    stringlength = 0;
    return 0;
}



0



687 / 393 / 201

Регистрация: 19.12.2016

Сообщений: 1,599

19.02.2022, 21:48

2

А у вас #include <cstring> подключен?



0



фрилансер

4792 / 4392 / 935

Регистрация: 11.10.2019

Сообщений: 11,568

19.02.2022, 21:56

3

Цитата
Сообщение от savvakhrenkov
Посмотреть сообщение

выдает предупреждения

текст предупреждений то какой ?

Добавлено через 2 минуты
savvakhrenkov, кстати, это учебное задание на динамические массивы или боевой код? В последнем случае можно всё упростить



0



0 / 0 / 0

Регистрация: 19.02.2022

Сообщений: 2

19.02.2022, 22:06

 [ТС]

4

C6385 Чтение недопустимых данных из «Array[invert].str»: доступный для чтения объем равен «size*1» байт, однако считать можно только «2» байт.
C6386 Переполнение буфера при записи в «Array[invert].str»: доступный для записи объем равен «size*1» байт, однако записать можно только «2» байт.

Добавлено через 4 минуты

Цитата
Сообщение от Алексей1153
Посмотреть сообщение

это учебное задание на динамические массивы или боевой код

Учебное задание
Надеюсь, вопросы по таким темам не запрещены правилами? Не нашел такого пункта, если что, поправьте меня.

Добавлено через 2 минуты

Цитата
Сообщение от ram876
Посмотреть сообщение

А у вас #include <cstring> подключен?

Подключена библиотека

. На

мой VS плюется и не находит.



0



687 / 393 / 201

Регистрация: 19.12.2016

Сообщений: 1,599

19.02.2022, 22:10

5

Цитата
Сообщение от savvakhrenkov
Посмотреть сообщение

не находит.

Как тогда strlen может работать?



0



24 / 57 / 31

Регистрация: 06.08.2020

Сообщений: 210

19.02.2022, 22:21

6

В VS нормально работает с #include<string> хотя да, по идее strlen это сишный прикол.

А предупреждения мне думается это студию смущает некоторая непонятность переменной invert. Но на работу это не влияет.



0



In my code, I am using an array xyz of 10 objects. When I am trying to access an element of the array using an unsigned int index like this: xyz[level], I get ‘Buffer overrun’ warning. Logically, I am pretty sure that level won’t exceed 10. How to avoid this warning?

Paul R's user avatar

Paul R

208k36 gold badges386 silver badges556 bronze badges

asked Jun 11, 2010 at 10:43

bdhar's user avatar

2

I’m probably teaching my grandmother to suck eggs here, but do remember that «level won’t exceed 10» is wrong for an array of size 10:

char a[10];
a[10] = '';  // Bug, and "Buffer Overrun" warning.

answered Jun 11, 2010 at 10:52

RichieHindle's user avatar

RichieHindleRichieHindle

270k47 gold badges356 silver badges398 bronze badges

3

Are you really sure? I never got this warning until now. So, double check.

Anyway, you can use the

#pragma warning( disable: 6386 )

preprocessor directive. I usually push and pop this to the «pragma stack»

#pragma warning( push )
#pragma warning( disable : 6386 )
// Some code
#pragma warning( pop )

as advised here.

answered Jun 11, 2010 at 10:53

mkluwe's user avatar

mkluwemkluwe

3,7732 gold badges27 silver badges45 bronze badges

1

Permalink

Cannot retrieve contributors at this time

description title ms.date f1_keywords helpviewer_keywords ms.assetid

Learn more about: Warning C6386

Warning C6386

11/04/2016

C6386

WRITE_OVERRUN

__WARNING_WRITE_OVERRUN

C6386

84e69fe8-8f03-4bb3-b194-e5551882e214

Warning C6386

Buffer overrun: accessing ‘buffer name‘, the writable size is ‘size1‘ bytes, but ‘size2‘ bytes may be written: Lines: x, y

Remarks

This warning indicates that the writable extent of the specified buffer might be smaller than the index used to write to it. This defect can cause buffer overrun.

Code analysis name: WRITE_OVERRUN

Example

The following code generates both this warning and C6201:

#define MAX 25

void f ( )
{
  char ar[MAX];
  // code ...
  ar[MAX] = '';
}

To correct both warnings, use the following code:

#define MAX 25

void f ( )
{
   char a[MAX];
   // code ...
   a[MAX - 1] = '';
}

See also

C6201

есть вот такой код, который для каждого объекта из folderList создает свой поток

DWORD hThreadArraySize = sizeof(HANDLE);
	hThreadArraySize*=folderList.size();
	hThreadArray = (HANDLE*)VirtualAlloc(NULL, hThreadArraySize, MEM_COMMIT, PAGE_READWRITE);
        for (std::list<FOLDERDESCRIPTOR>::iterator it = folderList.begin(); it != folderList.end(); it++, i++)
	{
               hThreadArray[i] = (*it).hThread = CreateThread();
	}

И на него выдается предупреждение анализатора кода

Warning C6386 Buffer overrun while writing to ‘hThreadArray’: the writable size is ‘hThreadArraySize’ bytes, but ‘8’ bytes might be written.

Почему оно возникает и как исправить? я все размеры проверил, все хорошо. Но что то же ему не нравистя

  • Forum
  • General C++ Programming
  • c++ buffer overrun warning error C6386

c++ buffer overrun warning error C6386

Hi all

The program below executes OK but getting one warning C6386 as shown below:
«warning C6386: Buffer overrun while writing to ‘df.m_Dats’: the writable size is ‘(unsigned __int64 size_t)*32′ bytes, but ’64’ bytes might be written.»
Any idea how to fix this? Is this vs2019 compiler bug and a known issue?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
                std::map< uint32_t, const NTDraw * > uidToDraw;
                
                struct NTDraw
               {
	             NTDraw *				m_Parent;
	             NTQuad				m_Rot;		
	             NTVector				m_Trans;
	             std::vector< NTDraw * >	m_Child;
	             const uint32_t			m_UID;
	             static uint32_t			s_NextUID;

	             NTDraw() : m_Parent( NULL ), m_Trans( 0.0f, 0.0f, 0.0f ), m_UID( s_NextUID++ ) {}
	             NTDraw( const NTQuad &rot ) : m_Parent( NULL ), m_Rot( rot ), m_Trans( 0.0f, 0.0f, 0.0f ), m_UID( s_NextUID++ ) {}
                };

                struct Data
		{
			uint32_t		m_UID;			
		};
		
		struct Dataframe
		{
			Data *		m_Dats;
			uint32_t	m_NumDats;
		};
                Dataframe* m_Dataframes;
                uint32_t	m_NumDataframes;

                m_NumDataframes = DataFrames;
	        m_Dataframes = new Dataframe[ DataFrames ];
	        uint32_t dfidx = 0;
	        for ( uint32_t f=0;f<NumFrames;f++ )
	        {
                  Dataframe df;
		  df.m_Dats = new Data[ uidToDraw.size() ];
		  df.m_NumDats = (uint32_t)uidToDraw.size();
		  uint32_t keyid = 0;
		  for ( auto ti = uidToDraw.begin(); ti != uidToDraw.end(); ++ti )
		 {
			Data frame;
			frame.m_UID = ti->first;
			df.m_Dats[ dataidx++ ] = frame;
		 }
                m_Dataframes[dfidx++] = df;
               }

Last edited on

I doubt it’s a vs2019 compiler bug, especially without more evidence. <Edit: As seeplus mentioned, sometimes intellisense can show errors, and it may be strict or give false positives, but it still might point to a possible improvement.>

You need to show a minimal reproducible example.

The following uses your code verbatim, but produces no warnings at warning level 4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <cstdint>
#include <map>

using std::uint32_t;

using UID = int;

struct Data {
	UID m_UID;
};

struct Key {
	Key& operator=(const Data& data)
	{
		return *this;
	}
};

struct Dataframe {
	Key* m_Dats;
	uint32_t m_NumDats;
};

int main()
{
	int dataidx = 0;
	std::map<UID, Data> uidToDraw;
	uidToDraw[0] = { 0 };

	//////////////////

	Dataframe df;
	df.m_Dats = new Key[uidToDraw.size()];
	df.m_NumDats = (uint32_t)uidToDraw.size();
	uint32_t keyid = 0;
	for (auto ti = uidToDraw.begin(); ti != uidToDraw.end(); ++ti)
	{
		Data frame;
		frame.m_UID = ti->first;
		df.m_Dats[dataidx++] = frame;
	}

	////////////////////
}

If I had to guess? It’s that cast to (uint32_t) from size_t (64-bit). Or, it’s complaining about how dataidx is only 32-bit.

Last edited on

Is this a build warning or an intellisense warning?

I was Running Code Analysis for C/C++ from VS2019 and ended up with this warning message, though my program executes OK. i am trying to figure out what went wrong in my code. Have updated above code and warning message occured at line 27: df.m_Dats[ dataidx++ ] = frame;

Last edited on

To make any kind of intelligent guess at what’ might be the problem, you should include the following in your code snippet:
— Declaration of Dataframe.
— Declaration of Key
— Declaration of uidToDraw
— Declaration of Data

I have added those declarations in the code above. Please check it.

Still a rubbish attempt at http://sscce.org/

1
2
3
4
5
6
7
8
for ( uint32_t f=0;f<NumFrames;f++ )
{
    df.m_Dats = new Data[ uidToDraw.size() ];
    for ( auto ti = uidToDraw.begin(); ti != uidToDraw.end(); ++ti )
    {
        df.m_Dats[ dataidx++ ] = frame;
    }
}

You don’t reset dataidx back to zero for your second pass through the f loop, so your second round of the ti loop uses a very non-zero dataidx value and keeps on incrementing from there on.

But how would we know, you’ve never shown how dataidx is declared or initialised.

Also, to stop your code looking like it’s been dragged through a hedge, only use spaces for indentation (most modern editors deal with indentation very well).
A heady mix of spaces and tabs is a mess when posted.

> The program below executes OK
Sure it does.
But the very nature of «undefined behaviour» necessarily includes «doing what I expected».

> Is this vs2019 compiler bug and a known issue?
It’s remarkable the number of wet behind the ears noobs who show up wondering whether it’s a compiler bug (a compiler used by many 1000’s of experienced professionals on a daily basis) is a possible alternative to their own code being wrong.

Topic archived. No new replies allowed.

Я пытаюсь реализовать сортировку слиянием в 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

Solution 1

Static code analysis is hard, tracing possible values of an expression like 3 + 2 * nNumItems is hard, and tracing actual possible values is often near to impossible. This is why it is a warning, not error. So far for the obvious.

Now, looking at how you describe that this warning behaves, I would bet on a «bug», or rather, I should say it with less stress, deficiency, in the static analyzer.

I can see some imaginary possible causes behind this warning on original nWords[1] = 2 and global nNumItems. They are really weird and I don’t think a reasonable analyst would add such rules to the analyzer. Also, I were right, then you should have these warnings on nWords[0] = 1 as well.

The fact that you don’t see them on that proves my ideas wrong, so I stop here.

Instead, I would like to focus on that static code analysis is hard. It does not matter how well-written the analyzer and its rules are. For some cases, it will make errors, and for other cases it will simply fail and won’t be even able to guess, and for other cases it will timeout and just let go. Until we have some breakthrough in AI or breakthrough in solving NP-hard problems, you will probably have to get used to the fact, that when you are using static code analyzers, then you have to write code in a way that they can comprehend, not count on that they can comprehend everything you can write.

Last thought, when I see this error:

file.cpp(18): warning C6386: Buffer overrun while writing to ‘nWords’: the writable size is ‘nTotal*4’ bytes, but ‘8’ bytes might be written.

the first thing that I notice is nTotal*4 and 8. If you were using a hardcoded values, you would probably get an error like

file.cpp(18): warning C6386: Buffer overrun while writing to ‘nWords’: the writable size is ‘1024’ bytes, but ‘8192’ bytes might be written.

The fact that you see nTotal*4 seems to imply that the static code analyzer actually failed to guess the value under nTotal and it left it as symbolic name, which formed an expression incomparable to 8. Therefore, the analyzer did theonly thing it could — it reported a problem, and described it as well as it could. Still, it’s just my guess.

// EDIT — note for Dan’s answer about guessing: nNumItems <- SIZE_MAX

I actually think that he’s may be quite about the SIZE_MAX. I played a bit with some SAT solvers from Microsoft, and one thing they did well was solving set of constraints in integer domain. Actually unsigned int x = SIZE_MAX; std::cout << ( (3+2*x)*sizeof(int) ); prints 4 (of course), and that is the only value of x for which the expression is less than 8.

I’m pretty sure that the constraint solver from microsoft I played with can detect this case when checking satisfiability of ((3+2*x)*4) < 8 in integer ring domain — hence the warning could be issued. However, I would expect the warning to include the result and print something like:

nTotal*4 < 8 when {nTotal=1,nNumItems=4294967295}`

since the analyzer had would have this information already. But then, that’s.. probably expecting too much from it. Developers behind it probably wouldn’t have thought of formatting such detailed warning message, or considered current format of the message to be more user-friendly.

Solution 2

Since nNumItems is global, it would appear that code analyzer thinks that nNumItems might be set to SIZE_MAX elsewhere before your code executes. You can see this with a sample like:

size_t nNumItems = 0;

void foo()
{
    nNumItems = SIZE_MAX;
}
void bar()
{
    const size_t nTotal = 3 + 2 * nNumItems;
    auto nWords = new int[nTotal];

    nWords[0] = 1;
    nWords[1] = 2;
}

int main()
{
    foo();
    bar();

    return 0;
}

Perhaps the best fix is to side-step the entire problem by using std::vector<int>.

Comments

  • I’ve read a lot about the Visual Studio Code Analysis warning C8386, but can’t figure out this particular issue with my code. I’ve reduced it to the following small program:

    unsigned int nNumItems = 0;
    
    int main()
    {
        int *nWords=nullptr;
        unsigned int nTotal;
    
        nTotal = 3 + 2 * nNumItems;
        nWords = new int[nTotal];
    
        nWords[0] = 1;
        nWords[1] = 2; // this is line 18, warning C6386
    
        delete[] nWords;
        return 0;
    }
    

    Analyze->Run Code Analysis->On Solution will give the following warning:

    file.cpp(18): warning C6386: Buffer overrun while writing to ‘nWords’: the writable size is ‘nTotal*4’ bytes, but ‘8’ bytes might be written.

    Is this legit? Now, if I move my global variable and make it local, the warning disappears!

    int main()
    {
        unsigned int nNumItems = 0;
    ...
    }
    

    But I can’t do this as in the full code, this is a member variable.

    Likewise, if I move the definition of nTotal into the ‘new int‘, I can also remove the warning:

        nWords = new int[3 + 2 * nNumItems];
    

    But I can’t do this as nWords is referred to in other places in the full code.

    Is this just an issue with the Visual Studio static code analyzer, or is it a legitimate issue with this code?

  • Static analysis is at least as hard as the halting problem. That’s why static-analyzers don’t always do a good job.

  • presumably other parts of the code want to change nNumItems

  • Warnings do not go away by restarting the IDE. Of course, you won’t see them directly because the message window will be empty on start, but the warning will reappear every time you compile the code. Besides, the other answers already proved it’s not a false positive. There are actual use cases where it could lead to a buffer overrun.

Recents

Понравилась статья? Поделить с друзьями:
  • C0036 97 ошибка лада веста
  • C0035 ошибка шевроле эпика
  • C0035 ошибка шевроле лачетти
  • C0035 ошибка шевроле круз как лечить
  • C0035 ошибка шевроле каптива