|
Salvatore Terress wrote: it fails.
Do not post questions with information like that. That can mean anything. What you need to post is the following.
1. What you expected it to do.
2. What it actually did.
From the little you posted I would have no idea what 'fails' means.
Salvatore Terress wrote: sudo
I suspect the real problem is exactly that.
It is not your code. It is how that gets executed within your code.
Define: A 'shell' is a operating system process that executes command line commands. Windows has the console window and powershell.
First step for debugging OS shell calls is always the print the command line before you call it. (Obviously removing security info if needed.) You do that even when the code works.
Then when there is a problem you use that output to figure out what is wrong.
Second step is to try the exact command in your own shell window. Often this will show the problem and allow you to figure out exactly how you need to modify the command.
Third step is that you need to understand that OS commands that are executed from your application can and problem will have an environment that is inherited from the application. This includes access permissions. (People often have problems with Windows Services because they do not understand this.)
Finally I can only note that with my limited experience I know that 'sudo' has its own oddities. For one, at least at times, I remember it requiring a password all the time. No password and it doesn't work.
Another trick I have used for OS commands in an application is the following.
1. Output the command - as I said above you should always be doing this.
2. Use an OS command to open a shell - NOTHING else. So you would see a OS shell pop on your display
3. Copy the command from the output, exactly as printed, and then run it in the shell that was popped.
4. Debug as normal for problems with that command.
That trick often helps to simulate the environment problem I suggested above.
|
|
|
|
|
For the removal.
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
|
Fairly common behaviour from someone who is on their (at least) fourth incarnation here.
|
|
|
|
|
It takes all kinds.
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
|
I wrote some C++ code to create a vector and then try to delete all occurrences of 3 in it:
vector<int> myVector = { 1, 2, 3, 4, 5, 3, 2 };
for (auto i = myVector.begin(); i != myVector.end(); i++)
{
if (*i == 3) myVector.erase(i);
}
However, it doesn't work right. It gives this error:
Expression: can't increment invalidated vector iterator
I guess you can't increment the iterator after you erase the element.
Anyone know how to fix this?
Thanks.
|
|
|
|
|
The problem comes because as soon as you remove an element then all the rest effectively move nearer the beginning, and thus their positions are out of sync with the iterator. You could try a reverse iterator as detailed at std::vector - cppreference.com[^].
|
|
|
|
|
As you guessed, erase invalidates all iterators on the container. Your problem is known as the Erase–remove idiom[^] There are different ways of solving it:
1. The "manual" way:
auto pos = myVector.begin();
size_t i=0;
while (pos != myVector.end())
{
if (*pos ==3)
{
myVector.erase(pos);
pos = myVector.begin() + i;
}
else
{
++i;
++pos;
}
}
2. The "semi-automatic" way:
auto pos = myVector.begin();
while (pos != myVector.end())
{
if (*pos ==3)
pos = myVector.erase(pos); else
++pos;
}
3. The "old fully automatic way":
myVector.erase(std::remove(myVector.begin(),
myVector.end(), 3),
myVector.end());
4. The "new fully automatic way" (since C++20):
std::erase (myVector, 3);
Disclaimer: I didn't compile any of the code above; some errors may/will exist
Mircea
|
|
|
|
|
Hi,
Is it OK to call std::async(BYTE *p) from inside a worker thread?.
How would it be possible to make sure async calls gets executed in order of first came , first executed just like calling a function synchronously?
|
|
|
|
|
|
(probably a TOmato vs toMAto kind of questions... )
At what point should I use variadic functions vs. keeping it local ?
I have a library that handles SQL queries.
is there a difference between something like :
(overly simplified)
std::string fullyFormedQuery = sprintf (queryFormat, param1, param2, ... );
void DoRequest( std::string fullyFormedQuery){
}
void DoRequest( std::string queryFormat, param1, param2, ... ){
std::string fullyFormedQuery= queryFormat(format, param1, param2, ... );
}
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
As you say it's more of a style question. My preference would be for the first option (pass fully formed string) because:
- there is less documenting to do
- some compilers (MSVC for one), check matching between format strings and parameters in (s)printf functions but don't do that in a user defined variadic function.
Mircea
|
|
|
|
|
thanks.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
Just noting that your examples leave out using bind variables.
My understanding, and I just googled to see if that seems to be correct, is that bind variables make optimizations in the database easier.
Not to mention of course that they are a better fit for avoiding SQL injection problems.
Setting up bind variables is rather complex so putting it in the method is going to be better.
|
|
|
|
|
Thanks.
We already have a complete (decades old) framework for SQL. (seems to be working fine)
maybe I should have left out the SQL reference and make it a more generic question.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
Maximilien wrote: complete (decades old) framework for SQL.
Then you should use the same idiom as the existing code. Changing it for some and not others just adds to the confusion. Although if a preference for one is given and there is a large amount of new work (new files not modifying existing code) then maybe go with there.
modified 20-Dec-23 12:00pm.
|
|
|
|
|
I will not change existing code; it's just too dangerous.
I'm just curious; if there's a best practice.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
My best practice doesn't fit either of your suggestions...
If I am creating a new database layer (which I have numerous times) then the caller would never provide the SQL.
If the business layer(s) need new database logic then the database layer should be modified to provide it.
The caller provides the parameters that would be used in the call.
Then within that database layer method it would decide how to process the parameters and SQL (provided by the method.)
So it looks like the following.
void DatabaseDoX(param1, param2,...)
{
std::string fullyFormedQuery = sprintf (SQL_X, param1, param2, ... );
There are quite a few variations on the above. For example consider the complication of a user initiated call where they might specify different 'query' terms (like data range, customer name, etc)
But all still hide the SQL.
Certainly there are design considerations for example your code might be coming from within the database layer (not a business call at all.) If so then I suspect that usage would actually vary depending on what the database layer was specifically doing in the code path.
|
|
|
|
|
I was playing around in Microsoft Visual C++, and I noticed something weird about this code:
void setname(char name[80])
{
strcpy_s(name, "joebob");
char name2[80];
strcpy_s(name2, "joebob");
}
It looks like the compiler complains about the first strcpy_s but not the second one. If I comment out the first one, the program compiles fine.
Can anyone explain this?
BTW, I know strcpy_s should probably take 3 arguments, but I'm trying to understand this weirdness.
Thanks.
|
|
|
|
|
Remember that in C arrays and pointers are the same thing so the argument name is a pointer to char. For the compiler, your code fragment is the same as:
void setname(char *name)
{
strcpy_s(name, "joebob");
char name2[80];
strcpy_s(name2, "joebob");
} In the case of the second call to strcpy_s , the compiler can figure out the size parameter through some template magic. For the first one however you have to use the explicit size form.
Mircea
|
|
|
|
|
It would help when posting questions that you include the exact error message(s), so it makes it clear what your problem is.
|
|
|
|
|
|
Should this work in C++?
long add1(a)
long a;
{
return a+1;
}
It doesn't seem to compile in Visual Studio. I got it from MIT's OpenCourseware.
Thanks.
|
|
|
|
|
That is the so called K&R syntax[^]. You can compile as C code but not as C++. The C++ version would be:
long add1 (long a) {
return a+1;
}
Mircea
|
|
|
|
|
mike7411 wrote: I got it from MIT's OpenCourseware.
I see the MIT is still at the cutting edge of technology !!
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
I am a little confused about when to use delete and delete[].
Is this correct?
int* numArray = new int[100];
delete numArray;
Or should it be this?
int* numArray = new int[100];
delete[] numArray;
I saw the former in an MIT lecture, and it looked suspicious. Both of them compile.
Thanks.
|
|
|
|