if (nullptr!=timing_info)
{
timing_info->h = start_time;
}
I get the following warning
autosar_cpp14 a5-1-1 violation
Using literal "NULL" other than type initialization, where symbolic names shall be used instead.
The autosar rule a5-1-1 reads
Rule A5-1-1 (required, implementation, partially automated) Literal
values shall not be used apart from type initialization, otherwise
symbolic names shall be used instead.
I never thought "nullptr" was a literal value. If it is a literal value, then what is the best way to handle this warning.
As you've already quoted, Rule A5-1-1 says
Rule A5-1-1 (required, implementation, partially automated)Literal
values shall not be used apart from type initialization,
otherwise symbolic names shall be used instead.
(source)
The idea behind this rule is that you should not use magic constants, i.e., don't write something like
// 100 is a magic constant. It's not clear what the next line means without comments.
if (list.size() > 100) {
std::cout << "error!";
} else {
std::cout << "everything ok!";
}
but rather, write
static constexpr auto maximum_allowed_size = 100;
// The next line speaks for itself: "if list is bigger than allowed ..."
if (list.size() > maximum_allowed_size) {
std::cout << "error!";
} else {
std::cout << "everything ok!";
}
This extra constant increases readability in most cases.
Since nullptr is a literal and you use that literal nullptr for something else than "type initialization", your code violates that rule A5-1-1.
I don't know if autosar intentionally discourages the use of literal nullptr, I personally don't see a reason why one should do this. Maybe it has been overseen (should be an exception).
You can rephrase your code to silence the checker:
if (timing_info) // implicitly convert pointer to bool
as that variant apparently makes the checker unhappy, too, here is another variant:
if (!!timing_info) // convert pointer to bool using double negation
You could also use casts, but I wouldn't do that. Frankly speaking, I like the original variant (if (nullptr != timing_info)) most.
Related
I have made a program to take in float inputs from a user to create a dynamic array (Then use those inputs with functions to find basic stuff like max,min,sum,avg but that stuff works fine so I don't think Ill include that here for the purpose of not creating a wall of code).
It works about half the time and while I have some theories about the cause I cant put my finger on a solution.
int main() {
int Counter = 0;
float *UsrIn = nullptr;
float Array[Counter];
My first thought was that the part below was the issue. My class hasn't really gone over what notation (I assume it refers to bytes so maybe scientific notation would work) to use with new that I can recall. I just tried 20 for the sake of testing and it seemed to work(probably a silly assumption in hindsight).
UsrIn = new float[(int)20];
cout << "Enter float numbers:" << endl;
cout << "Enter '9999999' to quit:" << endl;
cin >> *UsrIn; // User Input for pointer Dynamic Array
Array[Counter] = *UsrIn;
while(*UsrIn!=9999999) // User Input for Dynamic Array
{
Counter++;
UsrIn++;
cin >> *UsrIn;
Array[Counter] = *UsrIn;
}
delete UsrIn;
delete[] UsrIn;
My other thought was that maybe a pointer address was already in use by something else or maybe it was invalid somehow. I don't know of a way to test for that because the crash I occasionally get only happens when exiting the while loop after entering "9999999"
As a side note I'm not getting any warnings or error messages just a crashed program from eclipse.
Variable-length arrays are not universally supported in C++ implementations, although your compiler clearly supports them. The problem, from what you've described, is with this code:
int main() {
int Counter = 0;
float *UsrIn = nullptr;
float Array[Counter];
You're defining a variable-length array of size 0. So, although you're allocating 20 entries for UsrIn, you're not allocating any memory for Array. The intention of variable-length arrays is to allocate an array of a given size where the size is not actually known until run time. Based on your other code, that's not really the situation here. The easiest thing to do is just change the Array size to match your UsrIn size, e.g.:
float Array[20];
If you really want more of a dynamic behavior, you could use std::vector<float>
std::vector<float> Array;
...
Array.push_back(*UsrIn);
Where can I find the definitions for these two functions. Grepping for their name brings only declarations but I can't find their implementation in the source code.
Presumably you are looking for the C code function definitions. What I typically do when looking for the definitions is search across all files for the function name without the Rf_ but with the return type. For example, for Rf_error, I would search for void error. In this case you pretty quickly get (from src/main/errors.c#758, for R version 3.2.2):
void error(const char *format, ...)
{
char buf[BUFSIZE];
RCNTXT *c = R_GlobalContext;
va_list(ap);
va_start(ap, format);
Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
va_end(ap);
/* This can be called before R_GlobalContext is defined, so... */
/* If profiling is on, this can be a CTXT_BUILTIN */
if (c && (c->callflag & CTXT_BUILTIN)) c = c->nextcontext;
errorcall(c ? c->call : R_NilValue, "%s", buf);
}
Rf_warning is defined at line 262 of the same file.
Note the following lines in src/include/R_ext/Error.h
#ifndef R_NO_REMAP
#define error Rf_error
#define warning Rf_warning
#endif
R_NO_REMAP is usually not defined, so that means the macro error expands to Rf_error. So, in files that include Error.h, instances of error will be replaced with Rf_error by the preprocessor.
So you need to search for the function with the same return type and arguments. As BrodieG notes in his answer, the functions also usually (always?) have the same name, but without the Rf_ prefix.
Thanks to Duncan Murdoch for helpful pointers. Any errors are mine.
I am a C++ noob and I have written a method to get text file names including full-paths from a given directory. It gives a garbage value on the vector<wchar_t*> names. I used VS2010 debugger and analysed values. It looks like pointers are going out of scope. On the official C++ reference it says that push_back() copies values and seems like as I am pushing a pointer and it just copies pointers value.
static std::vector<wchar_t*> getFileNames(wchar_t* folder) // ex: c:\\textfiles\\My
{
using namespace std;
vector<wchar_t*> names;
wchar_t search_path[200];
swprintf(search_path, L"%s\\*.txt", folder); // ex: c:\\textfiles\\My\\*.txt
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile((wchar_t*)search_path, &fd);
if(hFind != INVALID_HANDLE_VALUE)
{
do
{
if(! (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) )
{
std::wstring fullPath(folder);
fullPath += L"\\";
fullPath += std::wstring(fd.cFileName); // cFilename has something like Info.txt
names.push_back((wchar_t*)fullPath.c_str());
}
}while(FindNextFile(hFind, &fd)); //goes out of scope and values become garbage
FindClose(hFind);
}
return names; //vector with garbage values
}
Is it possible to get wchar_t* pushed in to the vector someway, a better work around rather than dynamically allocating memory or using heap variables?
Can I get compiler warning for mistakes like this on VS2010 or any VS version(Now I only get casting warning and errors)?
swprintf might overflow the buffer.
(wchar_t*)search_path is a superfluous cast.
Never break out the big guns if you don't need them.
if(! (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) ) means you only ignore directories without interesting attributes.
fullPath += std::wstring(fd.cFileName); another superfluous cast.
names.push_back((wchar_t*)fullPath.c_str()); pushes a pointer to the internal buffer of fullpath into names, even though it will be destroyed at the end of the block.
What you should do is change the signature to
static std::vector<std::wstring> getFileNames(std::wstring folder)
Or at least
static std::vector<std::unique_ptr<wchar_t>> getFileNames(wchar_t* folder)
to take advantage of RAII and reduce the chance for errors.
In any case, you should rewrite the function, and should take advantage of the standard-library internally.
As an example, with the proper prototype:
static std::vector<std::wstring> getFileNames(std::wstring folder) {
std::vector<std::wstring> names;
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile((folder+L"\\*.txt").c_str(), &fd);
if(hFind == INVALID_HANDLE_VALUE)
return names;
auto lam = [](HANDLE* p){FindClose(*p);}
std::unique_ptr<HANDLE, decltype(lam)> guard(&hFind, lam);
folder += L"\\";
do {
if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
names.push_back(folder+fd.cFileName);
} while(FindNextFile(hFind, &fd));
return names;
}
Ideally, you should store class objects in your vector, instead of character pointers (or wchar_t pointers). You can do it, but it requires some extra work. That's the part that you're missing.
The issue you're seeing is exactly what you describe: the character arrays that are owned by the wstring objects are being destroyed when the wstring goes out of scope. By using wstring::c_str(), you are not creating an independent copy of the character array, you're just looking at the one that it already has created for its own use.
So you need a way to keep a character array around longer. Either you could use the wstring, or you need to copy the character array into one of your own.
The minimal change would be something like this:
std::wstring fullPath(folder);
fullPath += L"\\";
fullPath += std::wstring(fd.cFileName); // cFilename has something like Info.txt
wchar_t *wsz = new wchar_t[fullPath.size() + 1];
wcsncpy(wsz, fullPath.c_str(), fullPath.size());
names.push_back(wsz);
That's enough to get your strings into the vector, but because you're using character pointers, it's also your responsibility to clean them up. So when you are done using the vector, you will need to iterate through and delete each one of them before you let the vector be destroyed.
As I mention in a comment below, it's much simpler to use a std::vector. There are libraries that can help you with the memory management parts, if you must use wchar_t*. You caould take a look at the Boost Smart Pointer library, for example.
The variable fullPath is a local variable.
It goes out of scope.
That is the reason the pointers are becoming junk.
Allocate a dynamic memory as
vector<wstring*> names;// instead of vector<wchar_t*> names;
std::wstring *fullPath = new wstring(folder);
Never store references of objects into a list if you are not aware of their scope.
I am doing one project in which I define a data types like below
typedef QVector<double> QFilterDataMap1D;
typedef QMap<double, QFilterDataMap1D> QFilterDataMap2D;
Then there is one class with the name of mono_data in which i have define this variable
QFilterMap2D valid_filters;
mono_data Scan_data // Class
Now i am reading one variable from a .mat file and trying to save it in to above "valid_filters" QMap.
Qt Code: Switch view
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
The transferring is done successfully but then it gives run-time error
Windows has triggered a breakpoint in SpectralDataCollector.exe.
This may be due to a corruption of the heap, and indicates a bug in
SpectralDataCollector.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
Can anyone help in solving this problem. It will be of great help to me.
Thanks
Different issues here:
1. Using double as key type for a QMap
Using a QMap<double, Foo> is a very bad idea. the reason is that this is a container that let you access a Foo given a double. For instance:
map[0.45] = foo1;
map[15.74] = foo2;
This is problematic, because then, to retrieve the data contained in map[key], you have to test if key is either equal, smaller or greater than other keys in the maps. In your case, the key is a double, and testing if two doubles are equals is not a "safe" operation.
2. Using an int as key while you defined it was double
Here:
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
i is an integer, and you said it should be a double.
3. Your loop only test for (i,j) = (0,0)
Are you aware that
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
is equivalent to:
Scan_Data.valid_filters[0][0]=valid_filters[0][0];
printf("\nValid_filters=%f",Scan_Data.valid_filters[0][0]);
?
4. Accessing a vector with operator[] is not safe
When you do:
Scan_Data.valid_filters[i][j]
You in fact do:
QFilterDataMap1D & v = Scan_Data.valid_filters[i]; // call QMap::operator[](double)
double d = v[j]; // call QVector::operator[](int)
The first one is safe, and create the entry if it doesn't exist. The second one is not safe, the jth element in you vector must already exist otherwise it would crash.
Solution
It seems you in fact want a 2D array of double (i.e., a matrix). To do this, use:
typedef QVector<double> QFilterDataMap1D;
typedef QVector<QFilterDataMap1D> QFilterDataMap2D;
Then, when you want to transfer one in another, simply use:
Scan_Data.valid_filters = valid_filters;
Or if you want to do it yourself:
Scan_Data.valid_filters.clear();
for(int i=0;i<n;i++)
{
Scan_Data.valid_filters << QFilterDataMap1D();
for(int j=0;j<m;j++)
{
Scan_Data.valid_filters[i] << valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
If you want a 3D matrix, you would use:
typedef QVector<QFilterDataMap2D> QFilterDataMap3D;
#include <iostream>
#include <vector>
using namespace std;
struct s_Astruct {
vector <int> z;
};
int main ()
{
vector <s_Astruct> v_a;
for(int q=0;q<10;q++)
{
v_a.push_back(s_Astruct());
for(int w =0;w<5;w++)
v_a[q].z.push_back(8);
}
vector <s_Astruct> * p_v_a = & v_a;
cout << p_v_a[0]->z[4]; //error: base operand of '->' has non-pointer type
//'__gnu_debug_def::vector<s_Astruct, std::allocator<s_Astruct> >'
}
There seems to be some issue with this sort of operation that I don't understand. In the code that I'm working on I actually have things like p_class->vector[]->vector[]->int; and I'm getting a similar error.
You want to do this:
cout << ((*p_v_a)[0]).z[4];
What you are doing is dereferencing the pointer by using [] and grabbing the 0'th offset, and then trying to dereference the non-pointer.
Another way to do it (which is just ugly):
cout << (p_v_a[0][0]).z[4];
p_v_a is a vector*, making p_v_a[0] a vector (since p_v_a[0] is equivalent to *(p_v_a+0)), so using the pointer to member operator (->) isn't going to work on that. You likely want (*p_v_a)[0].z[4].
When you use the index [] operator on the pointer, that also dereferences it. Using the infix dereference operator -> on the non-pointer type then results, correctly, in the error you describe.
In the following:
vector<s_Astruct>* p_v_a = &v_a;
cout << p_v_a[0]->z[4]
You have a pointer to a vector, but you didn't dereference that pointer before attempting to call operator[]. You then attempted to dereference the s_Astruct at index 0, but that is not a pointer.
Try this:
vector<s_Astruct>* p_v_a = &v_a;
cout << (*p_v_a)[0].z[4];
Hope that helps.
This was driving me buggo- I'd managed to get
std::cout << (nsNLs->back()).name
working, but I couldn't get the index array reference to work, (even with parens I didn't need).
std::cout << ||here?|| nsNLs ||here?|| [ intVal ] ||here?|| name
I tried every variation of dereferenceing and parenthesizing around the pointer to the vector, without hitting on ( ||thing pointed to by|| passedVariable )[ ].name
"." works because at the end of the two stage dereference, we're looking at an instance of the struct, not anything pointed to something, just a concrete chunk of memory.
#Mark, very clear explanation, you lead with something that works, and the operation is unusual enough that I feel better with the parens around the vector object dereference AND the array element / pointer dereference. I saw your solution, tried it, and it worked.
#Tomalek, Your answer is second easiest to follow and gets an extra point in my book for showing the problem, going through it step by step, explaining the error, and then suggesting the fix. Slightly sportier than Mark, only one set of parentheses.
#user470379, your answer is correct and you show a successful solution, but its bit harder to follow and the answer is at the end.
Thank you all three, I voted you up.