I seem to get an erroneous warning message from Visual Studio 2019 (16.5 Preview but also in 16.4 and earlier) Code Analysis tool. Is this a bug, or am I really just missing something?
The warning generated (exactly) is:
warning C6385: Reading invalid data from 'prodlist': the readable size is '(size_t)*32+8' bytes, but '64' bytes may be read.
Here's the code which generates the warning (as minimal as possible)
#include <cstdint>
#include <string>
#include <iostream>
struct Product {
std::string price_profile;
};
int getNumRows() {
return 5;
}
Product *getProductsFromDB( int &numelements ) {
numelements = 0;
const int num_rows = getNumRows();
if ( num_rows == 0 ) {
numelements = 0;
return nullptr;
}
Product *prodlist = new Product[num_rows];
for ( int i = 0; i < num_rows; ++i ) {
prodlist[i].price_profile = "test"; // Warning on this line
}
numelements = num_rows;
return prodlist;
}
int main() {
int num_rows;
Product *prodlist = getProductsFromDB( num_rows );
for ( int i = 0; i < num_rows; ++i ) {
std::cout << prodlist[i].price_profile;
}
getchar();
}
If I change the price_profile to an int (and its corresponding value), or if I change num_rows to a constant (like 5) then the warning goes away.
It seems in Visual Studio 2019 Microsoft is enforcing SAL analysis rules on C and C++ code by default, even though there are still plenty of false positives like your case here.
One thing you can do for now is disable the warning giving a false positive:
#pragma warning(push)
#pragma warning(disable:6385)
Product *getProductsFromDB( int &numelements ) {
...
}
#pragma warning(pop)
Related
My code goes through the values of each sample in a JSON file and gives out the number of sorting comparisons, the amount of memory, and time it takes for the sorting to happen. But for some reason the code is throwing me an error. Would love it if someone could help me out.
I'm getting a [json.exception.type_error.302] for some reason in my code. I know what the error means but I don't know where there's a fault
To be exact, this is the error I'm getting - "libc++abi.dylib: terminating with uncaught exception of type nlohmann::detail::type_error: [json.exception.type_error.302] type must be number, but is null"
#include <iostream>
#include <fstream>
#include "json.hpp"
#include "mergesort.h"
#include "insertionsort.h"
#include "quicksort.h"
#include <ctime>
#include <iomanip>
int main(int argc, char* argv[]) {
std::ifstream file;
file.open(argv[1]);
nlohmann::json jsonObject;
if (file.is_open()) {
file >> jsonObject;
} else {
std::cout << "Invalid Argument" << std::endl;
}
clock_t mergeTime, quickTime, insertTime;
extern int insertMemAccesses, insertCompare, mergeMemAccesses, mergeCompare, quickCompare, quickMemAccesses;
// std::cout << jsonObject;
// nlohmann::json jsonOutput;
std::cout << "Sample,InsertSortTime,InsertionSortCompares,InsertionSortMemaccess,MergeSortCompares,MergeSortMemaccess,QuickSortTime,QuickSortCompares,QuickSortMemaccess";
int arraysize = jsonObject["metadata"]["arraySize"];
int numsamples = jsonObject["metadata"]["numSamples"];
for (int i = 0; i <= numsamples; i++) {
std::string sample;
if (i < 9) {
sample = "Sample0" + std::to_string(i+1);
} else {
sample = "Sample" + std::to_string(i+1);
}
std::vector<int> insertion;
std::vector<int> merge;
std::vector<int> quick;
for(int j = 0; j <= arraysize; j++){
insertion.push_back(jsonObject[sample][j]);
merge.push_back(jsonObject[sample][j]);
quick.push_back(jsonObject[sample][j]);
}
insertTime = clock();
InsertionSort(&insertion);
insertTime = clock() - insertTime;
insertTime = ((unsigned long)insertTime)/CLOCKS_PER_SEC;
mergeTime = clock();
MergeSort(&merge);
mergeTime = clock() - mergeTime;
mergeTime = ((unsigned long)mergeTime)/CLOCKS_PER_SEC;
quickTime = clock();
QuickSort(&quick);
quickTime = clock() - quickTime;
quickTime = ((unsigned long)quickTime)/CLOCKS_PER_SEC;
std::cout<<sample<<",";
printf("%.6lu,%d,%d,%.6lu,%d,%d,%.6lu,%d,%d\n",insertTime,insertCompare,insertMemAccesses,mergeTime,mergeCompare,mergeMemAccesses,quickTime,quickCompare,quickMemAccesses);
insertCompare = 0;
insertMemAccesses = 0;
mergeCompare = 0;
mergeMemAccesses = 0;
quickCompare = 0;
quickMemAccesses = 0;
}
return 0;
}
Step through the code, and which line does the exception happen on? If you don't have a way to step through, then add in some std::cerr calls throughout to see where it is failing. I would assume that the error occurs on one of the push_back lines, most likely the first. You have j <= arraysize, which most likely goes out of bounds, so when you try to access jsonObject[sample][arraysize] this causes the error.
Also, you could probably just do quick = merge = insertion = jsonObject[sample].get<std::vector<int>>(), instead of needing the loop
Why doesn't the following code work? It prints INT_MAX. But if I uncomment the two lines in the inner for loop, then it works fine (prints 2). I can't combine the two macros like that? Not sure if further detail is needed...pretty self explanatory.
Thanks.
#include <iostream>
#include <limits.h>
using namespace std;
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
int main(int argc, char **argv)
{
int N = 100;
int *drop = new int[N+1];
drop[0] = 0; drop[1] = 1; drop[2] = 1;
for(int i=3; i<=N; i++)
{
drop[i] = INT_MAX;
for(int start=1; start<=i; start++)
{
drop[i] = min(drop[i], max(start, drop[i-start]+1));
//int x = max(start, drop[i-start]+1);
//drop[i] = min(drop[i], x);
}
}
cout<<drop[3]<<endl;
return 0;
}
Put brackets around the terms in your macros:
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
As it is, this:
drop[i] = min(drop[i], max(start, drop[i-start]+1));
is expanding to this (without brackets):
drop[i] < start > drop[i-start]+1 ? start: drop[i-start]+1 ? drop[i] : start > drop[i-start]+1 ? start: drop[i-start]+1;
which may not evaluate in the order you intend. Using brackets enforces the correct order of operations.
As noted in the comments, you shouldn't use macros with expressions that have side effects if the macro arguments are evaluated more than once.
C++ already has std::min and std::max defined in <algorithm>. You can change your code to a pure C++ version
#include <iostream>
#include <algorithm>
#include <limits>
using namespace std;
int main(int argc, char ** argv) {
int N = 100;
int * drop = new int[N + 1];
drop[0] = 0;
drop[1] = drop[2] = 1;
for (int i = 3; i <= N; ++i) {
drop[i] = numeric_limits<int>::max(); // <limits>
for(int start = 1; start <= i; ++start)
drop[i] = min(drop[i], max(start, drop[i - start] + 1)); // <algorithm>
}
cout << drop[3] << endl;
return 0;
}
Rather than an answer, it's a plead to all developers out there: please don't use macros like that. C++ offers template functions for these purposes. Remember that macros just substitute parameters rather than pre-evaluating them. Even if you add parentheses as samgak explained, this only fixes a half of the problem. Consider code like this:
int x = 5;
int y = max(++x, 0);
The caller would expect x=6 and y=6 after that; however the macro will get expended into
int y = (++x > 0)? ++x : 0;
causing x=7 and y=7.
Here is my code:
#include <cstdlib>
#include <stdio.h>
#define NUM_READINGS 3
int* readingsTotal;
int* readingsAverage;
int readingsIndex;
using namespace std;
void avgOf(int* toFindAvgOf, int size) {
int i;
for (i = 0; i < size; i++) {
// Add reading to total for each component.
readingsTotal[i] += toFindAvgOf[i];
// Once method has been iterated through n (NUM_READINGS) times:
if (readingsIndex == NUM_READINGS - 1) {
// Set the arithmetic mean.
readingsAverage[i] = readingsTotal[i] / NUM_READINGS;
// Reset the total.
readingsTotal[i] = 0;
}
}
readingsIndex++;
}
int iterate(int findAvgOf) {
int toFindAvgOf[] = {findAvgOf, 20, 30};
avgOf(toFindAvgOf, sizeof (toFindAvgOf));
return readingsAverage[0];
}
int main(int argc, char** argv) {
readingsTotal = (int []){0, 0, 0};
readingsAverage = (int []){0, 0, 0};
int i;
for (i = 0; i < 3; i++) {
int smthd = iterate(12 + i * 2);
printf("%d\n", smthd);
}
return 0;
}
When I run this in netbeans c/c++, it builds with now errors but when it executes it fails and prints:
RUN FAILED (exit value 1, total time: 86ms)
When I go into debug mode it also fails immediately and gives the SIGSEGV error. From reading online I'm guessing there is some issue with the way I am dereferencing a pointer. But I have no clue where exactly it is failing at. I am pretty new to c++ so any help would be great!
In C, the sizeof function returns the size of the object in bytes.
So when you say:
sizeof (toFindAvgOf)
That will return 12 (assuming an int on your system is 4-bytes) thus causing an index out of bounds condition in the avgOf function.
To get the length of the array:
sizeof(toFindAvgOf) / sizeof(int)
I am trying to compile my code in VS 2010 that compiles and works in gcc, but I get a weird error on a lambda expression:
std::function<double (size_t level, size_t q)> doLevel = [&](size_t level, size_t q)
{ //line 52
double thisLevelP = density(q, data[level]);
if(level==T-1) return thisLevelP;
if(level==t-1) return thisLevelP*A(q,state)*doLevel(level+1,state);
double continuation = 0.0;
for(size_t i=0; i<Q; ++i)
{
continuation += A(q, i)*doLevel(level+1, i);
}
return thisLevelP*continuation;
};
The error is:
Error 1 error C2086: 'size_t &_T' : redefinition c:\users\ga1009\documents\phd\cpp\pmi\cpp\test\baumiterationtest.cpp 52
Error 2 error C2661: '`anonymous-namespace'::`anonymous-namespace'::<lambda1>::<lambda1>' : no overloaded function takes 8 arguments c:\users\ga1009\documents\phd\cpp\pmi\cpp\test\baumiterationtest.cpp 52
What is wrong?
As seen in the comments above by chris, lambdas with multiple return statements need an explicit return type which can be declared like this ->double.
More importantly though the offending line is the variable named t which is captured by the lambda. I originally though this was a name clash but as STL correctly points out it happens with any two names which are the same except one is capital. This is a compiler bug which is known and has been fixed in the newest versions.
double density(std::size_t, int)
{
return 0;
}
double A(std::size_t, int)
{
return 0;
}
int main(int argc, char *argv[])
{
int data[] = {1,2,3};
std::size_t T = 1;
std::size_t t = 2; //<<<<< change this name and it compiles
std::size_t state = 3;
std::size_t Q = 4;
std::function<double (int,int)> doLevel = [&](int level, int q)->double
{
double thisLevelP = density(q, data[level]);
if(level==T-1)
return thisLevelP;
if(level==t-1)
return thisLevelP*A(q,state)*doLevel(level+1,state);
double continuation = 0.0;
for(size_t i=0; i<Q; ++i)
{
continuation += A(q, i)*doLevel(level+1, i);
}
return thisLevelP*continuation;
};
}
I am currently rewriting a small project i written some time ago, and am replacing function pointers with std::function and lambdas.
While doing this i stumbled over an issue with for loops in lambdas.
in Visual Studio 2010 (with SP1) generates strange errors when for loops are used inside lambdas, IF the lambda is defined at file scope:
#include <iostream>
auto print_sum =
[]( int n )
{
int sum=0;
// line below generates:
// error C2143: syntax error : missing ')' before ';'
for( int i=1; i<=n; ++i )
sum += i;
std::cout << sum << "\n";
};
int main()
{
print_sum(3);
return 0;
}
following snippet however compiles fine:
#include <iostream>
int main()
{
auto print_sum =
[]( int n )
{
int sum=0;
for( int i=1; i<=n; ++i )
sum += i;
std::cout << sum << "\n";
};
print_sum(3);
return 0;
}
Both snippets compile fine using MinGW GCC 4.7.
Has anyone else observed this behaviour aswell?
Is this a bug in the lambda implementation of the Visual Studio?
Do you know any workarounds?
Edit:
bug report on microsoft connect:
https://connect.microsoft.com/VisualStudio/feedback/details/660742/error-with-for-loops-in-file-scope-lamdas-c-0x#details
I can verify this behavior on Visual Studio 2010 RTM. It appears to be limited to just for loops as the following compiles just fine.
auto print_sum =
[](int n)
{
int sum=0;
int i = 1;
while (i <= n)
{
sum += i;
i++;
}
std::cout << sum << "\n";
};
I would definitely alert microsoft to this issue by filing a bug on connect
http://connect.microsoft.com
Note: I don't 100% know if this is a bug but evidence suggests that it is