I have a piece of code in c++ which is working fine with gcc version 4.1.2 20071124 but giving warning with gcc version 4.4.6 20120305. Please suggest:
Code:
WriteLog(sgca_log_file,"Exception occured in load_sgsn_cdr_arch \n",true);
Warning: deprecated conversion from string constant to 'char*'
where Writelog is a function to print logs in specified log file:
void WriteLog(const char* fileName, const char* pLogMsg, bool pTimeRequired)
{
FILE *lFileDesc = NULL;
char lMessage[1000];
char lBuffer[1000];
char lDate[1000];
time_t lRawtime;
struct tm * lTimeinfo;
char LoaderLogFile[80];
char loaderHome[30];
char * pch;
char szdir[30];
try
{
memset(LoaderLogFile, '\0',80);
memset(lMessage, '\0', 1000);
memset(lBuffer, '\0', 1000);
memset(lDate, '\0', 1000);
time(&lRawtime);
lTimeinfo = localtime(&lRawtime);
strftime(lBuffer, 1000, "| %x - %X | ", lTimeinfo);
strftime(lDate, 1000, "%Y_%m_%d", lTimeinfo);
if (!strcmp(fileName,"default"))
{
strcpy(loaderHome, getenv("LOADER_HOME"));
sprintf(LoaderLogFile,"%s/log/Loader_%s.log",loaderHome,lDate);
}
else
sprintf(LoaderLogFile,"%s_%s.log",fileName,lDate);
if (!file_exists(LoaderLogFile))
{
if((pch=strrchr(LoaderLogFile,'/')) != '\0')
{
strncpy(szdir,LoaderLogFile,pch-LoaderLogFile+1);
if(file_exists(szdir))
{
lFileDesc = fopen(LoaderLogFile, "a");
fflush(lFileDesc);
fclose(lFileDesc);
}
else
{
sprintf (lBuffer,"Directory %s doesnot exist. Please check the configurations. Stopping the System. \n",szdir);
WriteLog("default",lBuffer,true);
StopSystem("default",lBuffer);
}
}
else
{
sprintf (lBuffer,"Invalid log file name %s \n",LoaderLogFile);
WriteLog("default",lBuffer,true);
StopSystem("default",lBuffer);
}
}
//! Check whether the timestamp also has to be written in the log file
if(pTimeRequired)
{
sprintf(lMessage, "%s%s\n", lBuffer, pLogMsg);
}
else
{
sprintf(lMessage, "%s\n", pLogMsg);
}
//! Open the log file in append mode
lFileDesc = fopen(LoaderLogFile, "a");
if(lFileDesc != NULL)
{
fprintf(lFileDesc, lMessage);
fflush(lFileDesc);
fclose(lFileDesc);
}
else
{
printf("Unable to open the file \n");
}
}
catch(...)
{
printf("Exception occured in WriteLog \n");
}
}
I would declare
void WriteLog(const char* fileName, const char* pLogMsg,
bool pTimeRequired);
because very probably you don't change the fileName or the pLogMsg
This is because string literals are non-modifiable. But for backwards compatibility they are allowed to be treated as char* instead of const char*.
Get rid of the warning by changing your function to:
void WriteLog(char* fileName, const char* pLogMsg, bool pTimeRequired);
Related
I've been searching for hours today and just can't find anything that works out for me. The one I've just had a look at, with no luck, is "How to convert UTF-8 encoded std::string to UTF-16 std::string".
My question is, with a brief explanation:
I want to make a valid NTLM hash in std C++, and I'm using OpenSSL's library to create the hash using its MD4 routines. I know how to do that, so does anyone know how to convert the std::string into a UTF-16 LE encoded string which I can pass to the MD4 functions to get a correct digest?
So, can I have a std::string which holds the char type, and convert it to a UTF16-LE encoded variable length std::string_type? Whether that be std::u16string, or std::wstring?
And would I use s.c_str() or s.data() and would the length() function report correctly in both cases?
I think something like this should do the trick:
std::string utf16_to_utf8(std::u16string const& s)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t, 0x10ffff,
std::codecvt_mode::little_endian>, char16_t> cnv;
std::string utf8 = cnv.to_bytes(s);
if(cnv.converted() < s.size())
throw std::runtime_error("incomplete conversion");
return utf8;
}
std::u16string utf8_to_utf16(std::string const& utf8)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t, 0x10ffff,
std::codecvt_mode::little_endian>, char16_t> cnv;
std::u16string s = cnv.from_bytes(utf8);
if(cnv.converted() < utf8.size())
throw std::runtime_error("incomplete conversion");
return s;
}
Note: that std::wstring_convert is deprecated in C++17 but I still favor using it rather than a non-standard library given that it is portable, has no dependencies and will no doubt remain until replaced.
And, if all else fails, you can reimplement these same functions with alternative code without changing any other part of the application.
Apologies, firsthand... this will be an ugly reply with some long code. I ended up using the following function, while effectively compiling in iconv into my windows application file by file :)
Hope this helps.
char* conver(const char* in, size_t in_len, size_t* used_len)
{
const int CC_MUL = 2; // 16 bit
setlocale(LC_ALL, "");
char* t1 = setlocale(LC_CTYPE, "");
char* locn = (char*)calloc(strlen(t1) + 1, sizeof(char));
if(locn == NULL)
{
return 0;
}
strcpy(locn, t1);
const char* enc = strchr(locn, '.') + 1;
#if _WINDOWS
std::string win = "WINDOWS-";
win += enc;
enc = win.c_str();
#endif
iconv_t foo = iconv_open("UTF-16LE", enc);
if(foo == (void*)-1)
{
if (errno == EINVAL)
{
fprintf(stderr, "Conversion from %s is not supported\n", enc);
}
else
{
fprintf(stderr, "Initialization failure:\n");
}
free(locn);
return 0;
}
size_t out_len = CC_MUL * in_len;
size_t saved_in_len = in_len;
iconv(foo, NULL, NULL, NULL, NULL);
char* converted = (char*)calloc(out_len, sizeof(char));
char *converted_start = converted;
char* t = const_cast<char*>(in);
int ret = iconv(foo,
&t,
&in_len,
&converted,
&out_len);
iconv_close(foo);
*used_len = CC_MUL * saved_in_len - out_len;
if(ret == -1)
{
switch(errno)
{
case EILSEQ:
fprintf(stderr, "EILSEQ\n");
break;
case EINVAL:
fprintf(stderr, "EINVAL\n");
break;
}
perror("iconv");
free(locn);
return 0;
}
else
{
free(locn);
return converted_start;
}
}
I'm using "readline" library to create a console interface for my program. I'm able to autocomplete words using tab, but when I have words that share the same prefix like (car, card, carbon) it always chooses the shortest one. Here's my program (mostly taken from link):
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <iostream>
const char *words[] = {"add", "remove", "rm", "update", "child", "children", "wife", "wifes"};
void *xmalloc (int size)
{
void *buf;
buf = malloc (size);
if (!buf)
{
fprintf (stderr, "Error: Out of memory. Exiting.\n");
exit (1);
}
return buf;
}
char *dupstr (const char *str)
{
char *temp;
temp = (char *) xmalloc (strlen (str) + 1);
strcpy (temp, str);
return (temp);
}
char *my_generator (const char *text, int state)
{
static int list_index, len;
const char *name;
if (!state)
{
list_index = 0;
len = strlen (text);
}
while (name = words[list_index])
{
list_index++;
if (strncmp (name, text, len) == 0) return dupstr (name);
}
// If no names matched, then return NULL.
return ((char *) NULL);
}
static char **my_completion (const char *text, int start, int end)
{
char **matches = (char **) NULL;
if (start == 0)
{
matches = rl_completion_matches ((char *) text, &my_generator);
}
else rl_bind_key ('\t', rl_abort);
return matches;
}
int main (int argc, char *argv[])
{
char *buf;
rl_attempted_completion_function = my_completion;
while ((buf = readline(">> ")) != NULL)
{
rl_bind_key ('\t', rl_complete);
if (strcmp (buf, "exit") == 0) break;
else if (buf[0] == '\0') continue;
else
{
std::cout << buf << std::endl;
add_history (buf);
}
}
free (buf);
return 0;
}
Is it possible to list all matches on double tab just like in ubuntu terminal?
I managed to get it to work by commenting out these two lines:
rl_bind_key ('\t', rl_complete);
and:
else rl_bind_key ('\t', rl_abort);
The default completion behaviour of readline works exactly like in ubuntu terminal, one tab to complete and two tabs to list possible completions. Not sure though what's the default completion function that's binded with the tab key, from the documentation i thought it was rl_possible_completions but it didn't give the same results.
Also i added the following line to my_completion function to prevent adding space at the end of the matched word:
rl_completion_append_character = '\0';
I removed dupstrfunction it and replaced it with the native strdup function instead (this has nothing to do with the auto complete problem, it's just to remove unnecessary code).
This is the final code:
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <iostream>
const char *words[] = {"add", "remove", "rm", "update", "child", "children", "wife", "wives"};
// Generator function for word completion.
char *my_generator (const char *text, int state)
{
static int list_index, len;
const char *name;
if (!state)
{
list_index = 0;
len = strlen (text);
}
while (name = words[list_index])
{
list_index++;
if (strncmp (name, text, len) == 0) return strdup (name);
}
// If no names matched, then return NULL.
return ((char *) NULL);
}
// Custom completion function
static char **my_completion (const char *text, int start, int end)
{
// This prevents appending space to the end of the matching word
rl_completion_append_character = '\0';
char **matches = (char **) NULL;
if (start == 0)
{
matches = rl_completion_matches ((char *) text, &my_generator);
}
// else rl_bind_key ('\t', rl_abort);
return matches;
}
int main (int argc, char *argv[])
{
char *buf;
rl_attempted_completion_function = my_completion;
while ((buf = readline(">> ")) != NULL)
{
// rl_bind_key ('\t', rl_complete);
if (strcmp (buf, "exit") == 0) break;
else if (buf[0] == '\0')
{
free (buf);
continue;
}
else
{
std::cout << buf << std::endl;
add_history (buf);
}
free (buf);
buf = NULL;
}
if (buf != NULL) free (buf);
return 0;
}
The answer by razzak is almost correct, but this NULL must be added at the end of array of strings:
const char *words[] = {"add", "remove", "rm", "update", "child", "children", "wife", "wives", NULL};
Some changes for nonwarning compilation in my_generator() function:
while ((name = words[list_index++]))
{
if (strncmp (name, text, len) == 0) return strdup (name);
}
I'm having a __stack_chk_fail in the main thread.
I have no idea why is this happening?
I got the codes from this website:
http://www.packetizer.com/security/sha1/
Im trying to add a function to compute the digest of a file using the example.
.h file
#include <stdio.h>
#include <string>
std::string digestFile( char *filename );
.cpp file
std::string SHA1::digestFile( char *filename )
{
Reset();
FILE *fp = NULL;
if (!(fp = fopen(filename, "rb")))
{
printf("sha: unable to open file %s\n", filename);
return NULL;
}
char c = fgetc(fp);
while(!feof(fp))
{
Input(c);
c = fgetc(fp);
}
fclose(fp);
unsigned message_digest[5];
if (!Result(message_digest))
{ printf("sha: could not compute message digest for %s\n", filename); }
std::string hash;
for (int i = 0; i < 5; i++)
{
char buffer[8];
int count = sprintf(buffer, "%08x", message_digest[i]);
if (count != 8)
{ printf("converting unsiged to char ERROR"); }
hash.append(buffer);
}
return hash;
}
__stack_chk_fail occurs when you write to invalid address.
It turns out you do:
char buffer[8];
int count = sprintf(buffer, "%08x", message_digest[i]);
C strings are NUL-terminated. That means that when sprintf writes 8 digits, it adds 9-th char, '\0'. But buffer only has space for 8 chars, so the 9-th goes past the end of the buffer.
You need char buffer[9]. Or do it the C++ way with std::stringstream, which does not involve any fixed sizes and thus no risk of buffer overrun.
My program should open a file, the file path is retrieved from the command line using argv[1].
I then try to open the file using fopen but my program crashes because the filepath I use doesn't contain double backslashes so fopen doesn't work.
I've tried to write my own convert function and using print to check the result looked good at first sight.
The problem is that when I use the returned const char* as argument it gives me a weird result.. my code:
#include <stdio.h>
#include <stdlib.h>
#include <string>
const char* ConvertToPath(std::string path)
{
std::string newpath = "";
for(unsigned int i = 0; i < path.length(); ++i)
{
if(path[i] == '\\')
{
newpath += "\\\\";
}
else
{
newpath += path[i];
}
}
printf("%s \n", newpath.c_str());
return newpath.c_str();
}
bool OpenDBC(const char* path)
{
const char* file = ConvertToPath(path);
printf("%s \n", file);
FILE* dbc = fopen(file, "rbw");
if (!dbc)
return false;
return true;
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Error, expected DBC file.");
getchar();
return -1;
}
if (!OpenDBC(argv[1]))
{
printf("There was an error opening the DBC file.");
getchar();
return -1;
}
getchar();
return 0;
}
Opening a DBC file with my program gives me the following result:
D:\\Achievement.dbc
a
So it looks like const char* file only contains 1 char of the file path, why?
You do not need the ConvertToPath function at all. Double backslashes are only needed in string literals. Never in variables such as a std::string.
I compiled your code on Linux and can not replicate your result
Running ./filereader "D:\\Achievement.dbc" results in
D:\\Achievement.dbc
D:\\Achievement.dbc
Running ./filereader "D:\\\\Achievement.dbc" results in
D:\\\\Achievement.dbc
D:\\\\Achievement.dbc
The later is what you want because command line arguments need to be escaped. Then you can remove the ConvertToPath.
I work with C++ and SQLite3 (with Microsoft Visual C++ 2008) and would like to read a value from my database and store it in a variable to work with it on.
The select statement works fine, but every time I viewed the callback function and try to read the value from char **argv, I get "only" the memory address, or the first ASCII character of the value, which is in the database. What am I doing wrong?
Here is the callback function:
static int callback(void *pArg, int argc, char **argv, char **azColName)
{
fprintf(f, "Callback aufgerufen!\n");
int i;
for(i=0; i<argc; i++)
{
fprintf(f, azColName[i]);
fprintf(f, " = ");
if(argv[i]){
fprintf(f, argv[i]);
//unsigned int x = argv[i];
}
else
fprintf(f, "NULL");
fprintf(f, "\n");
}
fprintf(f, "\n");
return 0;
}
I tried it without the callback function, but again I get the same result and I've tried different ways to store the value in a variable.
while (sqlite3_step(stmt) == SQLITE_ROW)
{
fprintf(f, "%s\n", sqlite3_column_text(stmt, 0));
//const unsigned char *c = sqlite3_column_text(stmt, 0);
fprintf(f, "%u\n", sqlite3_column_int(stmt, 0));
//unsigned int z = *sqlite3_column_int(stmt, 0);
stmt_count++;
}
Is it perhaps not possible to access the value or to store it in a variable?
I don't see why you need a callback - this should work (depending on the size of the data):
char myvalue[100];
while (sqlite3_step(stmt) == SQLITE_ROW)
{
strcpy( myvalue, (const char *) sqlite3_column_text(stmt, 0) );
// do something with myvalue
stmt_count++;
}