I am using getopt_long to process command line arguments in a C++ application. The examples all show something like printf("Username: %s\n", optarg) in the processing examples. This is great for showing an example, but I want to be able to actually store the values for use later. Much of the rest of the code uses string objects instead of char* so I need to cast/copy/whatever the contents of optarg into a string.
string bar;
while(1) {
c = getopt_long (argc, argv, "s:U:", long_options, &option_index);
if (c == -1) break;
switch(c)
{
case 'U':
// What do I need to do here to get
// the value of optarg into the string
// object bar?
bar.assign(optarg);
break;
}
}
The above code compiles, but when it executes I get an Illegal instruction error if I try to print out the value of bar using printf (it seems to work just fine for cout).
// Runs just fine, although I'm not certain it is actually safe!
cout << " bar: " << bar << "\n";
// 'Illegal instruction'
printf(" bar: %s\n", bar);
I do not know enough about command line debugging to better dig into what the illegal instruction might be. I had been running valgrind, but the sheer volume of memory errors that result from this error have made it difficult for me to pinpoint exactly what might be causing this error.
You told printf that you were suppling a c style string (null terminated array of chars) when specifying %s, but you provided a string class instead. Assuming you are using std::string try:
printf("bar : %s\n", bar.c_str());
printf() can't handle C++ strings. Use bar.c_str() instead.
cout << " bar: " << bar << "\n";
is perfectly safe. What makes you think it might not be?
Related
Problem Description:
I have created a custom C++ function print() that is supposed to be pushed as a global onto a table to so the user can use the print() function to print to the debug console. This function works to some extent, however, when you try to print a string with a space in it (over one word) the function is not called at all... This has greatly confused me, as I don't know why. If I were to try and call something such as print("Hello!") the console will have "Hello!" printed to it, but if I were to try and print something such as print("Hello world!") the function will not be called at all, I know this because I have used a message box to alert when the function is called.
Additional Information:
So, the closest thing to this I could find was a question asking how to make a custom print function in C++ with the Lua C API then push it onto the global table. I can already do this, and my function works to some extent. My function isn't being pushed onto the Lua C API's global table, instead to a table that is created by me with lua_newtable(L, s);. However, I've tried it both ways and it makes no difference. This print function does not support tables nor function as of now, I'm just focused on finding out and fixing why the function can't print strings over one word. Just in case you were wondering, Lua v5.1.5 and Microsoft Visual Studio 2017 are used for this. Debug mode, x86.
Code (C++):
If anyone could help me fix this, that would be great!
#include <iostream>
#include <string>
#include <Windows.h>
#pragma comment(lib, "Lua.lib")
#include "lua.hpp"
#include "luaconf.h"
static int print(lua_State* LUASTATE)
{
MessageBoxA(NULL, "Custom print called.", "FUNCTION!", NULL);
int nargs = lua_gettop(LUASTATE);
std::string string = "";
for (int i = 1; i <= nargs; i++)
{
if (i > 1) string += " ";
switch (lua_type(LUASTATE, i))
{
case LUA_TSTRING:
string += (std::string)lua_tostring(LUASTATE, i);
case LUA_TNUMBER:
string += (int)lua_tonumber(LUASTATE, i);
case LUA_TBOOLEAN:
string += (bool)lua_toboolean(LUASTATE, i);
}
}
std::cout << string << "\n";
return 0;
}
int pushs(lua_State* LuaState)
{
luaL_openlibs(LuaState);
lua_newtable(LuaState);
lua_pushcfunction(LuaState, print);
lua_setglobal(LuaState, "print");
lua_settop(LuaState, 0);
return 0;
}
int main()
{
lua_State* ls = luaL_newstate();
lua_State* LS = lua_newthread(ls);
pushs(LS);
while (true)
{
std::cout << " ";
std::string inputo;
std::cin >> inputo;
luaL_dostring(LS, inputo.c_str());
lua_settop(LS, 0);
}
lua_close(LS);
return 0;
}
Main problem
std::cin >> inputo does not read a full line from the standard input. It just reads a single word. So when you type the following input line in your shell:
print("Hello world")
Your main loop breaks it into two separate strings:
print("Hello
world")
And these string are evaluated independently by the Lua interpreter. None of these strings are valid Lua statements, so the interpreter doesn't execute them. lua_dostring will return an error code, and let an error message on the Lua stack.
To work line by line on the standard input, you can use std::getline, which works well in a loop:
std::string line;
while (std::getline(std::cin, line)) {
// do something with line.
}
Side notes
What follows is not directly related to your bug, but look suspicious:
std::string += int (or bool) interprets the int as a single char, and append this single character to the string.
Your switch/case seems to be missing break statements.
lua_State* ls is never closed.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to add data into a text file. However, i see for some reason it produces garbage data. I also notice, it will input the correct data once, but then it follow with garbage data.
void TextFileLogger::log(std::string msg){
using namespace std;
//ofstream output_file("students.data", ios::binary);
std::ofstream logFile;
// creating, opening and writing/appending data to a file
char filename[] = "log.txt";
logFile.open(filename, ios::binary | ios::app |ios::out);
if (logFile.fail())
{
std::cout << "The " << filename << " file could not be created/opened!" << std::endl;
// 0-normal, non zero - some errors
}
else
{
if (!logFile.write((char*)&msg, sizeof(msg)))
{
cout << "Could not write file" << endl;
}
else
{
streamsize bytesWritten = logFile.tellp();
if (bytesWritten != sizeof(msg))
{
cout << "Could not write expected number of bytes" << endl;
}
else
{
logFile << msg << std::endl;
cout << "file written OK" << endl;
}
}
}
}
That one is fun!
(char*)&msg does not do what you expect: std::string is mainly a pointer to a dynamically-allocated buffer which contains the actual data. When you take the std::string's address and try to read what's inside, you get a view of its innards, not its data. Using a C++ static_cast here would have spared you the trouble by telling you that the conversion makes no sense. sizeof(msg) similarly returns the size of the std::string, not the length of its data.
So, your solution is: use msg.data() and msg.size(), it's exactly what they're designed for.
But... why would it (sometimes) output your string, and a bunch of garbage? Well, std::strings typically use SSO (Small String Optimization). The std::string actually contains a small buffer, to store short enough strings without dynamic allocation. When you inspect the whole std::string object, you see this buffer pass by.
You are writing the contents of the whole std::string object, with all the member variables that it contains internally.
You either want:
logFile << msg;
or if you really want to use write():
logFile.write( msg.c_str(), msg.length());
And, I wonder: Why do create/open the file in binary mode, when you write strings afterwards?
And finally, you write the data twice, the second time in your last else clause.
The problem is with this line:
if (!logFile.write((char*)&msg, sizeof(msg)))
It should be this:
if (!logFile.write(msg.c_str(), msg.length()))
Since you are passing a std::string into the function, you should take advantage of the functions it provides (c_str() and length()) instead of trying to cast it to a char* (this always gets messy, plus you are casting away the const, which is also typically bad).
This:
if (!logFile.write((char*)&msg, sizeof(msg)))
is wrong in so many ways. msg is not an array of char, it's a std::string - lying to the compiler by using a cast is always a bad thing to do. And the size of a string is not the size of the characters it contains. Why the heck are you not using the obvios:
logfile << msg << std::endl;
Replace sizeof(msg) with msg.size(), sizeof() is not doing what you think!
Also (char*)&msg does not do whatever you think, use msg.data() instead.
logFile.write((char*)&msg, sizeof(msg));
should be rewritten to:
logFile.write(msg.data(), msg.size());
or, even better, because ofstream overrides operator<< for std::string:
logfile << msg;
I'm trying to pretty print a Clang statement to a string so that the C/C++ code of the statement is printed. I do this in the following way:
//Generate string and string ostream.
string stmt;
raw_string_ostream stream(stmt);
//Get statement from ASTMatcher and print to ostream.
auto* statement = result.Nodes.getNodeAs<clang::Expr>(types[VAR_STMT]);
statement->printPretty(stream, NULL, PrintingPolicy(LangOptions()));
//Flush ostream buffer.
stream.flush();
cout << statement << endl;
This code compiles and runs fine. However, when I run the following code, I get the address of the statement object printed to the string. For instance, when I run this code, I get the following as output:
0x3ccd598
0x3ccd5b0
0x3ccd728
0x3ccdc88
0x3ccdd08
There isn't really a lot of documentation about printPretty(...) in Clang's documentation so what is the correct way to print the code of a statement to a string?
One solution I found while trying to get this to work is from a Clang developers post from 2013.
Instead of:
//Generate string and string ostream.
string stmt;
raw_string_ostream stream(stmt);
//Get statement from ASTMatcher and print to ostream.
auto* statement = result.Nodes.getNodeAs<clang::Expr>(types[VAR_STMT]);
statement->printPretty(stream, NULL, PrintingPolicy(LangOptions()));
//Flush ostream buffer.
stream.flush();
cout << statement << endl;
My code is now:
//Get the statement from the ASTMatcher
auto *statement = result.Nodes.getNodeAs<clang::Expr>(types[VAR_STMT]);
//Get the source range and manager.
SourceRange range = statement->getSourceRange();
const SourceManager *SM = result.SourceManager;
//Use LLVM's lexer to get source text.
llvm::StringRef ref = Lexer::getSourceText(CharSourceRange::getCharRange(range), *SM, LangOptions());
cout << ref.str() << endl;
This approach does seem to work though I'm not too sure of any potential downsides.
You appear to be confusing yourself because of your similar variable names. You have a variable stmt that is of type string and you have a variable statement that is (presumably) of type clang::Stmt *. The printPretty call is modifying the stream variable, which writes to stmt, and not statement. Then you print statement, the pointer to the clang type. So naturally, a cout call for a pointer type writes the pointer's address.
Change your cout line to write out stmt, and you'll get what you're expecting.
I just figured out that it's possible to print a statement into a string using a raw_string_ostream:
// stmt is the statement you wish to print
string stmtToString(Stmt *stmt){
clang::LangOptions lo;
string out_str;
llvm::raw_string_ostream outstream(out_str);
stmt->printPretty(outstream, NULL, PrintingPolicy(lo));
return out_str;
}
This has been driving my entire C++ class nuts, none of us has been able to find a solid solution to this problem.
We are passing information to our program through the Terminal, via argv* [1]. We would call our program ./main 3 and the program will run 3 times.
The problem comes when we are validating the input, we are trying to cover all of our bases and for most of them we are good, like an alphabetical character entered, a negative number, 0, etc. But what keeps passing through is an int followed by a str for example ./main 3e or ./main 1.3. I've tried this
( Ashwin's answer caught my eye ) but it doesn't seem to work or at least I can't implement it in my code.
This is my code now:
int main(int argc, char * argv[]){
if (!argv[1]) exit(0);
int x = atoi(argv[1]);
if (!x or x <= 0) exit(0);
// I would like to add another exit(0); for when the input mixes numbers and letters or doubles.
for (int i = 0; i < x; i++){
// rest of the main func.
}
Despite the title, it sounds like you really want to do is check whether every single character in the input argument is a digit. You can achieve this by iterating over it, checking that every element is a digit using std::isdigit.
Here's a sketch using the std::all_of algorithm:
size_t len = strlen(argv[1]);
bool ok = std::all_of(argv[1], argv[1] + len,
[](unsigned char c) { return std::isdigit(c); } );
You can add an extra check for the first element being '0' if needed.
If you want to convert a string to a number and verify that the entire string was numeric, you can use strtol instead of atoi. As an additional bonus, strtol correctly checks for overflow and gives you the option of specifying whether or not you want hexadecimal/octal conversions.
Here's a simple implementation, with all the errors noted (printing error messages from a function like this is not a good idea; I just did it for compactness). A better option might be to return an error enum instead of the bool, but this function returns a std::pair<bool, int>: either (false, <undefined>) or (true, value):
std::pair<bool, int> safe_get_int(const char* s) {
char* endptr;
bool ok = false;
errno = 0; /* So we can check ERANGE later */
long val = strtol(s, &endptr, 10); /* Don't allow hex or octal. */
if (endptr == s) /* Includes the case where s is just whitespace */
std::cout << "You must specify some value." << '\n';
if (*endptr != '\0')
std::cout << "Argument must be an integer: " << s << '\n';
else if (val < 0)
std::cout << "Argument must not be negative: " << s << '\n';
else if (errno == ERANGE || val > std::numeric_limits<int>:max())
std::cout << "Argument is too large: " << s << '\n';
else
ok = true;
return std::make_pair(ok, ok ? int(val) : 0);
}
In general, philosophical terms, when you have an API like strtol (or, for that matter, fopen) which will check for errors and deny the request if an error occurs, it is better programming style to "try and then check the error return", than "attempt to predict an error and only try if it looks ok". The second strategy, "check before use", is plagued with bugs, including security vulnerabilities (not in this case, of course, but see TOCTOU for a discussion). It also doesn't really help you, because you will have to check for error returns anyway, in case your predictor was insufficiently precise.
Of course, you need to be confident that the API in question does not have undefined behaviour on bad input, so read the official documentation. In this case, atoi does have UB on bad input, but strtol does not. (atoi: "If the value cannot be represented, the behavior is undefined."; contrast with strtol)
what i'm writing is simple, well, it should be, but i'm getting this error and i don't know what else to do, my code look like this
int main()
{
char *option;
while(strcmp(option,"exit")!=0){
int opt = GetSystemDefaultUILanguage();
std::string lang;
switch(opt)
{
case 3082:
lang = "number 3082";
break;
case 1033:
lang = "number 1033";
break;
}
std::cout<<lang<<'\n';
std::cin>>option;
}
}
when i compile it there isn't errors, but when i run it, i get a this error
Project xxxx raised exception class EAccessViolation with message 'Access violation at address zzzzz'.Process stopped. Use Step or Run to continue.
EDITED:
This is my full code, now is more simple, but still the same result.
even if i try with an if/else statement it wont work, need some help here, thanks
Your program will always get an access violation because of the following lines:
char *option;
while(strcmp(option,"exit")!=0){
std::cin>>option;
You never initialize the pointer option, but then try to use it. Change your code to this:
int main()
{
std::string option;
while(option != "exit")
{
int opt = GetSystemDefaultUILanguage();
std::string lang;
switch(opt)
{
case 3082:
lang = "number 3082";
break;
case 1033:
lang = "number 1033";
break;
}
std::cout<<lang<<std::endl;
std::cin>>option;
}
}
I can't tell you the cause of the specific run-time error you're seeing, but I call tell you what's wrong with your program: hardcoded paths to user directories. Localized names are just one of a myriad of things that can go wrong with trying to guess the paths yourself.
DON'T DO THAT. Instead, read environment variables or call Shell APIs to find out where this particular user wants temporary data stored (or documents, pictures, desktop icons, etc).
Have a look at getenv("TEMP") and ShGetSpecialFolderPath
Your problem is this line:
std::cin>>option;
The variable option is declared as an uninitialized pointer to a character. Thus in the above statement, you are reading data into an unknown location.
Why do you use C style strings (char *) and C++ std::string?
You should get rid of C style strings (unless they are constant).
Try this:
#include <iostream>
#include <string>
int main(void)
{
std::string option;
do
{
std::cout << "Type exit to end program." << std::endl; // endl will flush output buffer
std::getline(cin, option); // Input a text line into "option".
} while (option != "exit"); // C-style string, used as a constant.
return 0;
}
You wrote
BlockquoteProject xxxx raised exception class EAccessViolation with message 'Access violation at address zzzzz'.Process stopped. Use Step or Run to continue.
So why don't you pause your program before crash, go to the location and put a breakpoint? If you still can't cope with that than upload your code to a filesharing server and give us the link ;)