VS2019, Code analysis warning: C6385 mystery
-
This is the full warning in question:
warning C6385: Reading invalid data from 'lines': the readable size is '(unsigned int)*4+4' bytes, but '8' bytes may be read.
I just (finally) converted a VS2013 project to VS2019, and as part of the cleanup I've been running the code analysis to help me spot issues. Below is a minimalist version of an oddity I found. So here's the case that started the journey. You can assume m_iNumLines is a UINT greater than 0; checking for this and other error conditions (e.g. that the pointer is not NULL) did not eliminate the warning. Simplified for clarity, this is verbatim code that triggered the warning:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 1: warning C6385: Reading invalid data from 'lines': the readable size is // '(unsigned int)\*4+4' bytes, but '8' bytes may be read. lines\[i\] = "TestString"; } delete\[\] lines;
}
I first tried covering every last (even absurd) error case to try and eliminate the warning, but changing
lines[i]
to*(lines + i)
did it:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 2: No warning \*(lines + i) = "TestString"; } delete\[\] lines;
}
I'm not sure what about handling of CStrings & pointers would make that an improvement. But here's what really baked my noodle. If I leave both lines in - even with the code that triggered thee warning first - I no longer get the warning:
void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 3: \*ALSO\* No warning lines\[i\] = "TestString"; \*(lines + i) = "TestString2"; } delete\[\] lines;
}
I also get no warning if I swapped the order (thinking maybe optimization - even in a debug build - made the first line do nothing). In searching I found others getting this warning also when using CStrings, but in situations much more convoluted than this, and I didn't see how it explained my case. Also I get the same results when using std::string, for what it's worth.
Look at me still talking when there's science to do When I look out there it makes me glad I'm not you
-
This is the full warning in question:
warning C6385: Reading invalid data from 'lines': the readable size is '(unsigned int)*4+4' bytes, but '8' bytes may be read.
I just (finally) converted a VS2013 project to VS2019, and as part of the cleanup I've been running the code analysis to help me spot issues. Below is a minimalist version of an oddity I found. So here's the case that started the journey. You can assume m_iNumLines is a UINT greater than 0; checking for this and other error conditions (e.g. that the pointer is not NULL) did not eliminate the warning. Simplified for clarity, this is verbatim code that triggered the warning:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 1: warning C6385: Reading invalid data from 'lines': the readable size is // '(unsigned int)\*4+4' bytes, but '8' bytes may be read. lines\[i\] = "TestString"; } delete\[\] lines;
}
I first tried covering every last (even absurd) error case to try and eliminate the warning, but changing
lines[i]
to*(lines + i)
did it:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 2: No warning \*(lines + i) = "TestString"; } delete\[\] lines;
}
I'm not sure what about handling of CStrings & pointers would make that an improvement. But here's what really baked my noodle. If I leave both lines in - even with the code that triggered thee warning first - I no longer get the warning:
void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 3: \*ALSO\* No warning lines\[i\] = "TestString"; \*(lines + i) = "TestString2"; } delete\[\] lines;
}
I also get no warning if I swapped the order (thinking maybe optimization - even in a debug build - made the first line do nothing). In searching I found others getting this warning also when using CStrings, but in situations much more convoluted than this, and I didn't see how it explained my case. Also I get the same results when using std::string, for what it's worth.
Look at me still talking when there's science to do When I look out there it makes me glad I'm not you
Could the
operator[]
be doing something under the covers?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
-
This is the full warning in question:
warning C6385: Reading invalid data from 'lines': the readable size is '(unsigned int)*4+4' bytes, but '8' bytes may be read.
I just (finally) converted a VS2013 project to VS2019, and as part of the cleanup I've been running the code analysis to help me spot issues. Below is a minimalist version of an oddity I found. So here's the case that started the journey. You can assume m_iNumLines is a UINT greater than 0; checking for this and other error conditions (e.g. that the pointer is not NULL) did not eliminate the warning. Simplified for clarity, this is verbatim code that triggered the warning:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 1: warning C6385: Reading invalid data from 'lines': the readable size is // '(unsigned int)\*4+4' bytes, but '8' bytes may be read. lines\[i\] = "TestString"; } delete\[\] lines;
}
I first tried covering every last (even absurd) error case to try and eliminate the warning, but changing
lines[i]
to*(lines + i)
did it:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 2: No warning \*(lines + i) = "TestString"; } delete\[\] lines;
}
I'm not sure what about handling of CStrings & pointers would make that an improvement. But here's what really baked my noodle. If I leave both lines in - even with the code that triggered thee warning first - I no longer get the warning:
void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 3: \*ALSO\* No warning lines\[i\] = "TestString"; \*(lines + i) = "TestString2"; } delete\[\] lines;
}
I also get no warning if I swapped the order (thinking maybe optimization - even in a debug build - made the first line do nothing). In searching I found others getting this warning also when using CStrings, but in situations much more convoluted than this, and I didn't see how it explained my case. Also I get the same results when using std::string, for what it's worth.
Look at me still talking when there's science to do When I look out there it makes me glad I'm not you
-
This is the full warning in question:
warning C6385: Reading invalid data from 'lines': the readable size is '(unsigned int)*4+4' bytes, but '8' bytes may be read.
I just (finally) converted a VS2013 project to VS2019, and as part of the cleanup I've been running the code analysis to help me spot issues. Below is a minimalist version of an oddity I found. So here's the case that started the journey. You can assume m_iNumLines is a UINT greater than 0; checking for this and other error conditions (e.g. that the pointer is not NULL) did not eliminate the warning. Simplified for clarity, this is verbatim code that triggered the warning:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 1: warning C6385: Reading invalid data from 'lines': the readable size is // '(unsigned int)\*4+4' bytes, but '8' bytes may be read. lines\[i\] = "TestString"; } delete\[\] lines;
}
I first tried covering every last (even absurd) error case to try and eliminate the warning, but changing
lines[i]
to*(lines + i)
did it:void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 2: No warning \*(lines + i) = "TestString"; } delete\[\] lines;
}
I'm not sure what about handling of CStrings & pointers would make that an improvement. But here's what really baked my noodle. If I leave both lines in - even with the code that triggered thee warning first - I no longer get the warning:
void CTestClass::SetText()
{
CString* lines = new CString[m_iNumLines];for (UINT i = 0; i < m\_iNumLines; i++) { // Case 3: \*ALSO\* No warning lines\[i\] = "TestString"; \*(lines + i) = "TestString2"; } delete\[\] lines;
}
I also get no warning if I swapped the order (thinking maybe optimization - even in a debug build - made the first line do nothing). In searching I found others getting this warning also when using CStrings, but in situations much more convoluted than this, and I didn't see how it explained my case. Also I get the same results when using std::string, for what it's worth.
Look at me still talking when there's science to do When I look out there it makes me glad I'm not you
FWIW, Visual Studio's C++ analysis is so bad, I keep it turned off. (Yes, it can find errors, but the number of false positives makes it pretty much worthless.)