<Unable to read memory> c++ - c++

I am trying to run this code in console app in vs 2013 but when I run the code give following error:
-argv[1] 0x00000000 <NULL> char *
<unable to read memory>
this is the main function code:
int main(int argc, char **argv)
{
set_new_handler(memory_err);
if (strcmp(argv[1], "lit") == 0) {
// For Rules
TransPar par;
get_args(par, argc, argv); // get arguments
gen_rules(par); // generate rules (really, just transactions)
}
else if (strcmp(argv[1], "seq") == 0) {
// For Sequences
SeqPar par;
get_args(par, argc, argv); // get arguments
gen_seq(par); // generate sequences
}
else if (strcmp(argv[1], "tax") == 0) {
// For Rules with Taxonomies
TaxPar par;
get_args(par, argc, argv); // get arguments
gen_taxrules(par); // generate rules (really, just transactions)
}
else if (strcmp(argv[1], "-version") == 0) {
print_version();
return 0;
}
else {
cerr << "Synthetic Data Generation, ";
print_version();
cerr << "Usage: " << argv[0] << " lit|tax|seq [options]\n";
cerr << " " << argv[0]
<< " lit|tax|seq -help For more detailed list of options\n";
return 1;
}
return 0;
}
Also I should mentioned the source code was built for Unix but I modified it for running to win.

You need to check if argc >= 2 before using argv[1]. If the user doesn't supply any arguments then you are accessing an argument that doesn't exist.
According to the C and C++ standards, argv[argc] is guaranteed to be a null pointer, which is what you're seeing here; you're passing a null pointer to strcmp() and this is causing the crash. (Side note: accessing argv[argc + 1] is undefined behavior so you need to be especially careful when accessing indices 2+.)

Related

C++ command line interface help message wont display [duplicate]

This question already has answers here:
How to compare strings
(4 answers)
Closed 1 year ago.
I am trying to make a CLI app in C++. This is my first time coding in C++.
I have this c++ code:
#include <iostream>
// using namespace std;
static void help(std::string argv)
{
std::cerr << "Usage:" << argv << " [options]\n"
<< "Options:\n"
<< "-h (--help): Displays this help message.\n"
<< "-o (--output=[output file]): Specifies the output file.\n"
<< "-p (--ports=[ports]) Sets the ports to scan.\n"
<< std::endl;
}
int main(int argc, char** argv)
{
if (argc > 1)
{
std::cout << argv[1] << "\n";
if (argv[1] == "-h" || argv[1] == "--help")
{
help(argv[0]);
return 0;
}
}
else
{
std::cout << "No arguments were given" << "\n";
};
};
// g++ -o cli main.cpp
It works! When I compile it, it successfully outputs No arguments were given, but when I run cli -h, I can see argv[1] is -h, but nothing is outputted.
What did I do wrong?
In your string comparison, argv[1] is a C string: a null-terminated char array. You cannot compare these with == and get the result you expect. If, however, you assign it to a std::string you can compare it with "-h" and "--help" the way you want.
std::string arg1 = argv[1];
if (arg1 == "-h" || arg1 == "--help") {
help(argv[0]);
return 0;
}
Alternatively you could use std::strcmp to compare C strings without creating a new std::string. In order to do this, you'll need #include <cstring>.
if (std::strcmp(argv[1], "-h") == 0 || std::strcmp(argv[1], "--help") == 0) {
help(argv[0]);
return 0;
}

piping stockfish misbehaves in fedora

Somewhere in my project I use fork and pipe to execute another process and pipe its I/O to communicate with it (I'm writing it in C++). There is no problem when I compile it in Ubuntu 14.04, it will work just fine, but I compiled it in fedora on a WMWare virtual machine and strange things began to happen. If I run the binary in terminal, there is no error but nothing will be written in the pipe (but getting streams of characters will work). I tried to debug my code in fedora, I put a break point in my code, but then a broken pipe signal was given when process tried to read from pipe (there were no signals when executing in terminal).
So, have any of you encountered such problems before? Is there any difference in piping between debian and red hat linux? Or is it because I'm running fedora on a virtual machine?
CODE:
int mFD_p2c [2];
int mFD_c2p [2];
int mEnginePID;
if (pipe(mFD_p2c) != 0 || pipe(mFD_c2p) != 0)
{
cout << "Failed to pipe";
exit(1);
}
mEnginePID = fork();
if (mEnginePID < 0)
{
cout << "Fork failed";
exit(-1);
}
else if (mEnginePID == 0)
{
if (dup2(mFD_p2c[0], 0) != 0 ||
close(mFD_p2c[0]) != 0 ||
close(mFD_p2c[1]) != 0)
{
cout << "Child: failed to set up standard input";
exit(1);
}
if (dup2(mFD_c2p[1], 1) != 1 ||
close(mFD_c2p[1]) != 0 ||
close(mFD_c2p[0]) != 0)
{
cout << "Child: failed to set up standard output";
exit(1);
}
string engine = "stockfish";
execlp(engine.c_str(), (char *) 0);
cout << "Failed to execute " << engine;
exit(1);
}
else
{
close(mFD_p2c[0]);
close(mFD_c2p[1]);
string str = "uci";
int nbytes = str.length();
if (write(mFD_p2c[1], str.c_str(), nbytes) != nbytes)
{
cout << "Parent: short write to child";
exit(1);
}
cout << "The following string has been written to engine:\n"
<< string(1, '\t') << str;
char readBuffer[2];
string output = "";
while (1)
{
int bytes_read = read(mFD_c2p[0], readBuffer, sizeof(char));
if (readBuffer[0] == '\n')
break;
readBuffer[bytes_read] = '\0';
output += readBuffer;
}
cout << "Got: " << output;
}
I see you're using Stockfish. I too have exactly experienced this behavior from Stockfish. The problem lies within how it handles output. Defined in misc.h:
#define sync_cout std::cout << IO_LOCK
And looking at the code again we'll see that IO_LOCK is an enum which is used in an overloaded friend operator for cout:
std::ostream& operator<<(std::ostream& os, SyncCout sc) {
static Mutex m;
if (sc == IO_LOCK)
m.lock();
if (sc == IO_UNLOCK)
m.unlock();
return os;
}
What I see here is that during using cout, a mutex is locked. I don't know how exactly this affects cout's output in a pipe instead of stdout, but I'm positive that this is the cause for the problem. You can check it by removing the lock functionality.
Edit: I forgot to mention that the pipe behavior is not different in linux based systems as mentioned before, but there might be slight differences between distributions handling mutexes used with pipes.
There are no differences in piping between debian and red hat, but the following list of questions may help you:
-Are the Ubuntu and the Fedora using the same architecture (64 bit vs 32) ?
-Are you using the same version of gcc (or any other compiler) ?
(Suggestion: use cerr for your error outputs, and maybe your debug output too -> you dup the standard outputs and inputs, so if something fails you may not see it)
Anyhow, here's how you turn it into a self-contained, compilable example:
stockfish
#cat stockfish
tr a-z A-Z #just so we do something
echo #need to end with a "\n" or else the parent won't break out of the while loop
Run command:
make pipes && PATH=.:$PATH pipes
pipes.cc
//pipes.cc
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
using namespace std;
int mFD_p2c [2];
int mFD_c2p [2];
int mEnginePID;
if (pipe(mFD_p2c) != 0 || pipe(mFD_c2p) != 0)
{
cout << "Failed to pipe";
exit(1);
}
mEnginePID = fork();
if (mEnginePID < 0)
{
cout << "Fork failed";
exit(-1);
}
else if (mEnginePID == 0)
{
if (dup2(mFD_p2c[0], 0) != 0 ||
close(mFD_p2c[0]) != 0 ||
close(mFD_p2c[1]) != 0)
{
cout << "Child: failed to set up standard input";
exit(1);
}
if (dup2(mFD_c2p[1], 1) != 1 ||
close(mFD_c2p[1]) != 0 ||
close(mFD_c2p[0]) != 0)
{
cout << "Child: failed to set up standard output";
exit(1);
}
string engine = "stockfish";
char *const args[]={};
int ret;
execvp(engine.c_str(), args);
//I need the endl here or else it doesn't show for me when the execvp fails; I wasn't able to compile the original exec command so I used a different one from the exec* family
cout << "Failed to execute " << engine << endl;
exit(1);
}
else
{
close(mFD_p2c[0]);
close(mFD_c2p[1]);
string str = "uci";
int nbytes = str.length();
if (write(mFD_p2c[1], str.c_str(), nbytes) != nbytes)
{
cout << "Parent: short write to child";
exit(1);
}
//My particular child process tries to read to the end, so give it the EOF
close(mFD_p2c[1]);
cout << "The following string has been written to engine:\n"
<< string(1, '\t') << str;
char readBuffer[2];
string output = "";
while (1)
{
int bytes_read = read(mFD_c2p[0], readBuffer, sizeof(char));
if (readBuffer[0] == '\n')
break;
readBuffer[bytes_read] = '\0';
output += readBuffer;
}
cout << "Got: " << output;
}
return 0;
}
output:
The following string has been written to engine:
uciGot: UCI

Variable length and position command line arguments

So, quick question:
I am tasked with making a program that reads in a file, does some fancy things, and writes out to an html file with the re-purposed text, all simple stuff.
Furthermore the program must be able to accept up to four command line arguments (but a minumum of two). The executable of course, the file it is reading in, the file name it will be reading out to, and finally a "-r" argument for more information on the file (the amount of paragraphs, etc).
So the question I have is as follows:
the "-r" argument can be anywhere in the arguments (as long as it comes after argv[0] of course), or it can be completely non-existent (as can the output file name).
This is still simple to do, a little tedious writing a bunch of if's or even a switch or two, but I can't help but think that there may be an easier way to accomplish this, rather than having a plethora of if statements.
Any help would be greatly appreciated. (I also suppose you don't need any code considering I don't exactly have a problem.)
Here is roughly how one might do it without a library:
GCC 4.8.2: g++ -Wall -Wextra -std=c++0x main.cpp
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
char* input = nullptr;
char* output = nullptr;
char* r_arg = nullptr;
--argc; ++argv; // Skip the program name.
const char* def_in = "default in";
const char* def_out = "default out";
const char* def_r = "default r";
while (0 < argc) {
if (std::string(argv[0]) == "-r") {
// This code requires a space after the "-r", which is unusual.
++argv;
--argc;
r_arg = argv[0]; }
else if (input == nullptr) {
input = argv[0]; }
else if (output == nullptr) {
output = argv[0]; }
else {
std::cerr << "error: unexpected arg '" << argv[0] << "'\n"; }
++argv;
--argc; }
if (input == nullptr) {
input = const_cast<char*>(def_in); }
if (output == nullptr) {
output = const_cast<char*>(def_out); }
if (r_arg == nullptr) {
r_arg = const_cast<char*>(def_r); }
std::cout << "input: " << input << "\n"
<< "output: " << output << "\n"
<< "r arg: " << r_arg << "\n";
return 0; }

Fingerprint calls cause segfaults in c++

I'm trying to write a simple fingerprint scanning program in c++ using libfprint, however it intermittently segfaults when run. Valgrind says the error is in the call to fp_enroll_finger which is consistent with my debugging, however beyond that I have absolutely no idea what is causing this error. Some of the times the program is run its fine, but some times it seems to consistently segfault for a period of time whenever the program is run?
Heres the code:
#include <iostream>
extern "C"
{
#include <libfprint/fprint.h>
}
using namespace std;
fp_dev * fpdev;
fp_print_data ** fpdata;
bool createDevice();
int main(int argc, char **argv)
{
int r = fp_init();
if(r != 0)
{
return r;
}
while(createDevice())
{
cout << "Scan right index finger" << endl;
int enrollStatus = fp_enroll_finger(fpdev, fpdata);
if(enrollStatus != 1)
{
cout << "Bad scan" << endl;
fp_dev_close(fpdev);
}
else
{
cout << "Good scan" << endl;
fp_print_data_save(fpdata[0], RIGHT_INDEX);
break;
}
}
if(fpdev != NULL)
{
fp_dev_close(fpdev);
}
fp_exit();
return 0;
}
bool createDevice()
{
fp_dscv_dev ** listOfDiscoveredDevs;
fp_dscv_dev * discoveredDevice;
listOfDiscoveredDevs = fp_discover_devs();
discoveredDevice = listOfDiscoveredDevs[0];
if(discoveredDevice != NULL)
{
cout << "Device found" << endl;
fpdev = fp_dev_open(discoveredDevice);
}
else
{
cout << "No device found" << endl;
return false;
}
fp_dscv_devs_free(listOfDiscoveredDevs);
return true;
}
You need to define fpdev and fpdata as:
fp_dev * fpdev;
fp_print_data * fpdata;
And use them as:
fp_enroll_finger(&fpdev, &fpdata);
Also don't forget to free fpdata when you no longer need it with fp_print_data_free
fp_dev * fpdev;
fp_print_data ** fpdata;
Will create 2 uninitialised pointers pointing to random memory location and leading to segfault once fp_enroll_finger will attempt to acces that location.
Checking fp_enroll_finger return value can be useful as well.

execvp() causing EXC_SOFTWARE and bizarre cin.getline loop?

I'm running some code on Mac OSX 10.6.6 and XCode 3.2.4 and I have some pretty standard code: fork(), if pid == 0 then execvp with a command and the args (the args include the command as the first element in the array, and the array is null terminated).
We're going over this in my Operating Systems class and our assignment is to write a simple shell. Run commands with their args and switches, both redirects (< and >) and pipe (|). I'm getting several problems.
1) Sometimes I get the EXC_SOFTWARE signal while debugging (so far I haven't gotten it if I run the app outside of XCode, but I'm new to Mac and wouldn't know what that would look like if I did)
2) Sometimes the getline for the next command gets junk that seems to be printed by other couts. This begins looping forever, exponentially breaking. I have tested with printing getpid() with every prompt and only the beginning process prints these out, I don't appear to have an accidental "fork bomb."
Here's what I have so far:
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
char** Split(char* buffer, int &count) {
count = 1;
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == ' ') {
count++;
}
}
const char* delim = " ";
char* t = strtok(buffer, delim);
char** args = new char*[count + 1];
for (int i = 0; i < count; i++) {
args[i] = t;
t = strtok(NULL, delim);
}
args[count] = 0;
return args;
}
void Run(char** argv, int argc) {
int pid = 0;
if ((pid = fork()) == 0) {
//for testing purposes, print all of argv
for (int i = 0; i < argc; i++) {
cout << "{" << argv[i] << "}" << endl;
}
execvp(argv[0], argv);
cout << "ERROR 1" << endl;
exit(1);
} else if (pid < 0) {
cout << "ERROR 2" << endl;
exit(2);
}
wait(NULL);
}
int main(int argc, char * const argv[]) {
char buffer[512];
char prompt[] = ":> ";
int count = 0;
while (true) {
cout << prompt;
cin.getline(buffer, 512);
char **split = Split(buffer, count);
Run(split, count);
}
}
It's exactly what I have, you should be able to cut, paste, and build.
I'm not the best at C++, and chances are there's a memory leak when I don't delete split but my main focus is the EXC_SOFTWARE signal and see what I'm doing wrong with my looping issue. Any thoughts?
EDIT:
The assignment requires very limited error checking and I'm assuming all input is correct. By correct I mean properly formatted and limited for my app to run the command, i.e. no bizarre space count, no & to run async, no multi piping commands, etc.
One problem is that you do not check the return from cin.getline(), so if you type EOF, the code goes into a tight loop. You're also leaking memory.
Try:
while (cout << prompt && cin.getline(buffer, sizeof(buffer))
{
int count = 0;
char **split = Split(buffer, count);
Run(split, count);
delete[] split;
}
The code in Split() does not really handle blank lines at all well. It seems to take an aeon to run execvp() when the only arguments are null pointers, which is what happens if you return a blank line.
I'm able to run multiple simple commands (such as 'vim makefile' and 'make shell' and 'ls -l' and 'cat shell.cpp' and so on - I even did a few with more than two arguments) OK with this, and I can quit the command (shell) with Control-D and so on. I have fixed it so it compiles with no warnings from g++ -O -Wall -o shell shell.cpp. I have not fixed the splitting code so that it handles empty lines or all blank lines correctly.
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
char** Split(char* buffer, int &count) {
count = 1;
for (size_t i = 0; i < strlen(buffer); i++) { // #1
if (buffer[i] == ' ') {
count++;
}
}
char** args = new char*[count + 1];
const char* delim = " ";
char* t = strtok(buffer, delim);
for (int i = 0; i < count; i++) {
args[i] = t;
t = strtok(NULL, delim);
}
args[count] = 0;
return args;
}
void Run(char** argv, int argc) {
int pid = 0;
if ((pid = fork()) == 0) {
//for testing purposes, print all of argv
for (int i = 0; i < argc; i++)
{
if (argv[i] != 0) // #2
cout << "{" << argv[i] << "}" << endl;
else
cout << "{ NULL }" << endl; // #3
}
execvp(argv[0], argv);
cout << "ERROR 1" << endl;
exit(1);
} else if (pid < 0) {
cout << "ERROR 2" << endl;
exit(2);
}
wait(NULL);
}
int main(int argc, char * const argv[]) {
char buffer[512];
char prompt[] = ":> ";
while (cout << prompt && cin.getline(buffer, sizeof(buffer))) // #4
{
int count = 0;
char **split = Split(buffer, count);
if (count > 0) // #5
Run(split, count);
delete[] split; // #6
}
}
I've marked the significant changes (they mostly aren't all that big). I'm compiling with GCC 4.2.1 on MacOS X 10.6.6.
I can't readily account for the garbage characters you are seeing in the buffer.
You're making the assumption that the input line contains one more token than spaces. This assumption may fail if the input line is empty, ends or begins with a space or contains multiple consecutive spaces. In these cases, one of the calls to strtok will return NULL, and this will crash the forked process when you try to print that argument in Run. These are the only cases in which I've encountered problems; if you've encountered any others, please specify your input.
To avoid that assumption, you could do the counting with strtok the same way you do the tokenizing. That's generally a good idea: if you need two things to coincide and you can do them the same way, you introduce an additional source of errors if you do them differently instead.