I'm practicing a c++ code on pthreads and there is some code I'm struggling to understand, I'm hoping someone here can give me some help with code explanation. Any help is appreciated, thanks.
01.#include <pthread.h>
02.#include <iostream>
03.#define SIZE 10
04.using namespace std;
05.int array[SIZE];
06.void *countNegativeNumbers(void *arg){...} //Assuming this function works properly
07.void *calAverageNumber(void *arg){...} //Assuming this function works properly
08.void *printReverseOrder(void *arg){...} //Assuming this function works properly
09.int main(){
10. pthread_t id,t1,t2,t3; //add pthreads and declare it here
11. int creatT; //declare the int variable for creat thread later
12. for(int i=0; i<10;i++){
13. cin>>array[i];}
14. creatT=pthread_create(&t1, NULL, countNegativeNumbers, NULL);
15. if(creatT){
16. cout << "ERROR; return code from pthread_create() is " << creatT << endl;
17. return -1;}
18. sleep(5); // busy wait.
19. // same as line 14 to 18 creat threads for t2,t3 and do if statement and busy wait.
20. creatT = pthread_join(t1, &status);
21. if(creatT){
22. cout<<" ERROR; failed to join "<<creatT<<endl;}
23. // same as line 20 to 22 terminate t2 and t3 here.
24. pthread_exit(0);
25. }
Question:
For lines 11-12, it uses a for loop to collect users' key in values, do we have any other options to do it? I cant use cin>>array[i]; since i is not declare here right?
Could anyone give me a detailed explanation for code lines 15 to 17? Do I really need those codes here? I think this is some kind of check if the thread is here or not?
For lines 20 to 22, pthread_join(thread, pointer) since int main has no pointer why I could not use NULL here?
line 24 pthread_exit(0); what is the 0 stand for?
Thanks for any helps here!
1 - declare the arraywith definite size at line 5 , u also can use any method for getting input but this here are working fine
2 - if u look at manual of pthread create return value section , u will see that it return zero on success and error number otherwise, here is link for ref
https://man7.org/linux/man-pages/man3/pthread_create.3.html
3- has same return value as pthread_create also for ref
https://man7.org/linux/man-pages/man3/pthread_join.3.html
4- it terminate the thread and release all the resources it was locked by it
https://man7.org/linux/man-pages/man3/pthread_exit.3.html
i also recommend using manual in future it will help u have better understanding of the code
For lines 11-12, it uses a for loop to collect users' key in values,
do we have any other options to do it? I cant use cin>>array[i]; since
i is not declare here right?
I don't see anything wrong with that. i is defined in for(int i=0; i<10;i++){, so it is valid inside the loop.
Could anyone give me a detailed explanation for code lines 15 to 17?
Do I really need those codes here? I think this is some kind of check
if the thread is here or not?
Those lines are checking the return value of pthread_create(), to make sure the thread was actually created. See the pthread_create() manual.
For lines 20 to 22, pthread_join(thread, pointer) since int main has
no pointer why I could not use NULL here?
pthread_join() is used to join with the created thread and get its return value once it exits. The pointer argument could be NULL if you don't care about the return value.
line 24 pthread_exit(0); what is the 0 stand for?
The return value. In this case, it is terminating the main thread and returning 0. see pthread_exit().
Related
I'm new to C++, coming from a python/kotlin background and so am having some trouble understanding what's going on behind the scenes here...
The Issue
I call the calculateWeights (public) method with its required parameters, it then calls a series of methods, including conjugateGradientMethod (private) and should return a vector of doubles. conjugateGradientMethod returns the vector of doubles to calculateWeights just fine, but calculateWeights doesn't return that to its caller:
The code
Callsite of calculateWeights:
Matrix cov = estimator.estimateCovariances(&firstWindow, &meanReturns);
cout << "before" << endl; // this prints
vector<double> portfolioWeights = optimiser.calculateWeights(&cov, &meanReturns);
cout << "after" << endl; // this does not print
Here's calculateWeights:
vector<double> PortfolioOptimiser::calculateWeights
(Matrix *covariances, vector<double> *meanReturns) {
vector<double> X0 = this->calculateX0();
Matrix Q = this->generateQ(covariances, meanReturns);
vector<double> B = this->generateB0();
vector<double> weights = this->conjugateGradientMethod(&Q, &X0, &B);
cout << "inside calculateWeights" << endl;
print(&weights); // this prints just fine
cout << "returning from calculateWeights..." << endl; // also prints
return weights; //this is where the SIGABRT shows up
The output
The output looks like this (I've checked and the weights it outputs are indeed numerically correct):
before
inside calculateWeights
1.78998
0.429836
-0.62228
-0.597534
-0.0365409
0.000401613
returning from calculateWeights...
And then nothing.
I appreciate this is printf debugging which isn't ideal and so I used Cion's debugger to find the following:
When I used CLion's debugger
I put a break point on the returns of the conjugateGradient method and calculateWeights methods. The debugger steppeed through the first one just fine. After I stepped over the return from calculateWeights, it showed me a SIGABRT with the following error:
Thread 1 "markowitzportfoliooptimiser" received signal SIGABRT, Aborted.
__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::deallocate (this=0x6, __p=0x303e900000762) at /usr/lib/gcc/x86_64-pc-cygwin/9.3.0/include/c++/ext/new_allocator.h:129
This is probably wrong but my first stab at understanding that is that I've overflowed over the size of vector<double> weights? It's only 6 doubles long and I never append anything to it after the loop below. This is how it's created inside conjugateGradientMethod:
How weights is created inside conjugateGradientMethod
vector<double> weights= vector<double>(aSize);
for (int i = 0; i < aSize; i++) {
weights[i] = aCoeff * a->at(i) + bCoeff* b->at(i);
}
Things I've tried
Initialising a vector for double weights in calculateWeights and passed a pointer to it to conjugateGradientMethod. Same result.
Having a public attribute on the class calculateWeights and conjugateGradientMethod both live on, and having it assign the weights to that (so both functions return void). Same result.
More generally, I've had this kind of issue before with passing up a return value from two functions deep. (If that makes sense?) ie passing from private method up to public method up to public method's callsite.
I'd be grateful for any advice on SIGABRT's in this context, I've read it's when abort() sends the calling process the SIGABRT signal, but am unsure how to make use of that in this example.
Also, I'm all ears for any other style/best practices that would help avoid this in future
Edit: Solution found
After much work, I installed and got Ubuntu 20.04 LTS up and running since I couldn't get the Address Sanitizer nor Valgrind to work via WSL on Windows 10 (first time on Linux - I kinda like it).
With Address Sanitizer now working, I was able to see that I was writing too many elements to a vector of doubles on two separate accounts, nothing to do with my weights vector as #Lukas Matena rightly spotted. Confusingly this was long before it ever got to the snippets above.
If anyone is finding this in the future, these helped me massively:
Heap Buffer Overflow
Heap vs Stack 1
Heap vs Stack 2
The error message says that it failed to deallocate an std::vector<double> when calculateWeights was about to return. That likely means that at least one of the local variables (which are being destroyed at that point) in the function is corrupted.
You seem to be focusing on weights, but since the attempts that you mention have failed, I would rather suspect X0 or B (weights is maybe not even deallocated at that point due to return value optimization).
Things you can try:
start using an address sanitizer like others have suggested
comment out parts of the code to see if it leads you closer (in other words, make a minimal example)
make one of the vectors a member variable so it is not destroyed at that point (not a fix, but it might give a clue about who is the offender)
You're likely doing something bad to the respective vector somewhere, possibly in calculateX0 or generateB0 (which you haven't shared). It may be delete-ing part of the vector, returning a reference to a temporary instead of a copy, etc. The SIGABRT at that return is where you were caught, but memory corruption issues often surface later than they're caused.
(I would have made this shorter and posted as a comment but I cannot as a newbie. Hopefully it will count as an "advice on SIGABRT's in this context", which is what was in fact asked for).
I was working on an assignment for class, and I think I got the program working properly, but now I would like to make some modifications to it just to better understand assert. The code is below -
#include <iostream>
#include <stdlib.h>
#include <assert.h>
using namespace std;
// Sample program that shows how command line arg works, in Unix g++
// Note argc and argv
// Also shows use of system call, that can launch any program
// system launches 'ls' to display files in the dir
void runAssert(int);
int main(int argc, char *argv[])
{
cout << "Number of inputs: " << argc << endl;
cout << "1st argument: " << argv[0] << endl;
system ("ls");
cout << "hello world" << endl;
runAssert(argc);
return 0;
}
void runAssert(int argc)
{
assert(argc > 4);
}
So the program is supposed to keep track of the arguments passed into main through command line. The professor specified that it should take 4 arguments. This code works, as far as I can tell, but I don't know what 4 commands to pass it? I do g++ assignment.cpp -o assignment
and then ./assignment -- But this last command only counts as one argument so the assert triggers. If I change the function to >= 1 then it works.
Another question I have is, how can I make it display an error message when it doesn't meet the requirements?
I have tried assert("Not the right amount of arguments", argc > 4) but then I get an error message about too many arguments being passed into main.
Thanks for any help, and sorry if my formatting is wrong. First time posting.
This is a completely incorrect usage of assert. Use assert to state things that you, as a programmer, think are logically necessary. It is logically possible for someone to call your program with fewer than 4 arguments, so assert is not correct.
A common usage of assert is at the start of a function. (This is not validating arguments.) Consider int foo(void *k){ assert(k != NULL); ...} Once again, this is not validating the argument k. The assertion is a piece of documentation that tells the human writing the code at the call site that foo is not to be called with a NULL argument. It is a claim that in the properly written code, it is a logical necessity that k be non-null. If you want to validate the argument and generate a pretty error message, use an if statement.
One thing about assert is that you should assume it does not execute in normal operation. Typically, the program will be compiled with -DNDEBUG, which will turn all of the assertions into whitespace.
ok the number of arguments should be checked before you start executing any of the program code.
In this case i guess the professor wanted you to pass the arguments passed to the program to ls .so it should be something like
./assignment -l -s -a
In the above case the -l -s and -a are the arguments.
You can use an if condition to check the number of arguments instead of assert.
if (argc < 4) {
// print the error message
// exit from program
}
Check answer by william to know the reason why not to use assert in this case
I don't know what 4 commands to pass
That's up to you. You could do:
./assignment a b c d
You will get get argv[1]="a", argv[2]="b", etc.
Parsing and using these arguments is up to you; in this context you could try to find an example of processing the arguments. Maybe print them in reverse order or something basic like that ?
Regarding assert(): your usage is not strictly correct as pointed out in another answer.
To answer your question, one simple way to display a message is by using && : https://stackoverflow.com/a/3692961/2750093
I don't think your professor would like that though, so you could do something a little bit more naive :
if (argc <= 4 )
{
printf("Not the right amount of arguments\n");
assert(false); // or return -1;
}
assert(condition) crashes the program with an error message like file bar.cc line 123: assertion failure 'condition'. As such it is not useful for the user, but it is useful for the developer.
Use assert to express expectations (on the state of certain internally controlled variables) that are assumed to hold in the code immediately following the assertion. Don't use assert to check user input (externally controlled variables), but throw an exception instead. Exceptions can be caught by the user, assertions cannot.
I'm extremely new to Ubuntu and PuTTY and putting a C++ file into it, but I'm having a problem with my C++ file. What I need the program to do is take a string entered from the Ubuntu side, put into the C++ program, and have it count how many strings are entered in and it sends back like so:
./myfile Supplying arguments now
Argument #0: ./myfile
Argument #1: Supplying
Argument #2: arguments
Argument #3: now
Number of arguments printed: 4
So, when I run my program down below, the program goes on forever and I can't step through it. What is causing it and why and/or what can I do to fix the problem?
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int count = 0;
while (*argv[argc] != NULL)
{
count++;
}
cout << count << endl;
system("PAUSE");
return 0;
}
Your code is an infinite loop because your while loop always checks the same condition. That's because argc never changes in your code.
What you meant to write is while (*argv[count] != NULL). However, what you meant isn't correct either.
C doesn't check array boundaries. When you read past an array boundary, you will not necessarily encounter a 0 value. You will read random garbage data which is in memory at that place.
You don't need to count the number of arguments yourself, because you already have it in the variable argc.
So a better solution to iterate all the command line arguments would be a for loop which increments count from 0 to argc.
What's the value of return when a C++ program fails? I've read some articles on this but nothing explicit.
If it doesn't return 0, is there a way into making the program return 0 or NULL on failure? I've red something about std::nothrow but found no practical examples so far. Can anyone clarify this to me?
The standard defines EXIT_SUCCESS and EXIT_FAILURE error codes with obvious meanings. They can be passed to either exit() function or explicitly returned with return statement from the main function. You can wrap the whole main function like
int main() try {
...
} catch(...) {
return EXIT_SUCCESS;
}
Your question is otherwise unclear.
NULL is just a macro for 0 as far as I know.
In stdlib.h:
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
The source (German) where I copied this from also states that using NULL is not recommended by Stroustrup.
The question is a bit unclear. The value that you return from main is precisely the value that you pass to the return statement in main. Nothing else can be said about that.
Now, what question should you really be asking? There are two aspects: One is the C++ side, and the other is the host side (i.e. the operating system).
You don't have any control over how any given operating system handles error conditions of programs that it launches. The only thing that the C++ standard guarantees are this:
If your main returns 0, EXIT_SUCCESS, or not at all, then the program ends in a manner that signals success; and
if your main returns EXIT_FAILURE, then the program ends in a manner that signals failure.
The actual return values of your program depend entirely on the platform, i.e. the operating system and the runtime environment.
For example, on Linux success is signalled via the value 0 and failure via a non-zero value, so a C or C++ program can be executed by simply returning the value of main() back to the OS (and defining EXIT_SUCCESS as 0). Other platforms may choose different semantics!
There is commonly assumed that a program returns 0 when it succeeds, and non-zero value otherwise.
You set the return value by returning from main function:
int main(int argc, char ** argv){
return 0; // Finish with success
}
or by passing the return code to the exit(int) function.
Also it is worth noting, that NULL is defined precisely as (void*)0 and is used when talking about pointers, not integers. If you don't understand what does it mean, read a decent C tutorial.
NULL is macro and it is same sa 0, it's defined like so:
#define NULL 0
when program fails it return 1 by default signaling the operating system that program failed.
if return value is grater than 1 then this is done by programer who wroted that program.
if program executes sucessefuly it always retun's 0.
you should never retun value other than 0 on program failure cos you will not know if it failed or not.
also if return value is lower thatn 0 that means fail as well.
so only sucess value is 0 or NULL which is same.
Successful runs usually have error code 0, anything other than 0 indicates some sort of error.
Error code Value Description
ERROR_SUCCESS 0 The action completed successfully.
ERROR_INVALID_DATA 13 The data is invalid.
ERROR_INVALID_PARAMETER 87 One of the parameters was invalid.
More : http://msdn.microsoft.com/en-us/library/windows/desktop/aa368542(v=vs.85).aspx
I have following code to divide one number recursively by another number:
#include <iostream>
using namespace std;
int divide(int number,int dividend){
int answer=0;
if (number>dividend || number==dividend ){
answer+=1;
return divide(number-dividend,dividend);
}
return answer;
}
int main(){
cout<<divide(20,5)<<endl;
return 0;
}
but unfortunately I get zero as answer. Do you see what is wrong?
Answer is a local variable. When you run this code, the first call to divide creates an instance of the answer variable, sets it to 0, and then increments it to 1. Then, when you recursively call divide again, it creates a brand new instance of the answer variable, sets that instance to 0, and then increments that instance to 1.
In your final call to divide, it creates a brand new instance of the answer variable, sets that instance to 0, but since now number<=dividend it doesn't increment it, and it returns that instance of answer which is 0.
In the if branch you are incrementing answer but returning something unrelated (the result of the recursive call). I am sure, this is not what you want. Go from there.
You are recursively running the following code:
if (number>dividend || number==dividend ){
answer+=1;
return divide(number-dividend,dividend);
}
But once the recursive calling ends (which is number < dividend), you will ignore the if statement and return 0;
You do int answer=0; in the start of function call, so when the if statement is wrong, it returns 0 so you should define it as input parameter (by reference call) or make it global (not recommended) and do not set it to zero, just set it before your recursive function call.