Where does the error come from? Valgrind / C / insertString - c

for one of my project i have to make a new version of the function insertString,you could see the code below:
This function always gives me the desired result, (I made some Unit test), however the main issue is this one: even if it works in my IDE (compilation etc) it won't pass unit test using Valgrind, is there anyone who could see the error?
char * insertString(const char * src, int insertPosition, const char * toBeInserted,int insertLength)
{
size_t outputSize=stringLength(src)+(size_t)insertLength;
char* output=malloc(sizeof(char)*(outputSize+1));
int i;
if(output==NULL)
{
fatalError("error during memory allocation in InsertString");
}
for(i=0;i<insertPosition;i++)
{
output[i]=src[i];
}
for(i=0;i<insertLength;i++)
{
output[i+insertPosition]=toBeInserted[i];
}
for(i=0;i<=insertLength;i++)
{
output[i+insertPosition+insertLength]=src[insertPosition+i];
}
output[outputSize]='\0';
return output;
}
thank's for everything, and have a good Sunday!

The terminating condition, i<=insertLength, in your last loop:
for(i=0;i<=insertLength;i++)
{
output[i+insertPosition+insertLength]=src[insertPosition+i];
}
has nothing to do with the length remaining in src. If insertLength is large enough, the code will read past the end of src.
Change it to something like (I think):
for(i=0;i<=strlen(src)-insertPosition;i++)
{
output[i+insertPosition+insertLength]=src[insertPosition+i];
}
Also, in my opinion the code could be made much more easily understood (and therefore verifiable) by using a running index for the output buffer instead of resetting it to 0 for each loop and adding other values for the subscript. Alternatively, I think using pointers to traverse the various buffers would be more readable:
char* tmp = output;
for(i=0;i<insertPosition;i++)
{
*tmp++ = *src++;
}
for(i=0;i<insertLength;i++)
{
*tmp++ = *toBeInserted++;
}
for(i=insertPosition;i<=strlen(src);i++)
{
*tmp++ = *src++;
}
*tmp++ = '\0';

Related

Issues using realloc (old size)

I'm trying to use realloc function in C, to dynamically operate on a char array of strings (char**).
I usually get a realloc():invalid old size error after 41st cicle of the for loop and I really can't understand why.
So, thanks to everyone who will help me ^-^
[EDIT] I'm trying to make the post more clear and following your advices, as a "new active member" of this community, so thank you all!
typedef struct _WordsOfInterest { // this is in an header file containing just
char **saved; // the struct and libraries
int index;
} wordsOfInterest;
int main() {
char *token1, *token2, *save1 = NULL, file[LEN], *temp, *word, **tokenArr;
int n=0, ch,ch2, flag=0, size, init=0,position,currEdit,init2=0,tempEdit,size_arr=LEN,
oldIndex=0,totalIndex=0,*editArr,counterTok=0;
wordsOfInterest toPrint;
char **final;
toPrint.index = 0;
toPrint.saved = malloc(sizeof(char*)*LEN);
editArr = malloc(sizeof(int)*LEN);
tokenArr = malloc(sizeof(char*)*LEN);
final = malloc(sizeof(char*)*1);
// external for loop
for(...) {
tokenArr[counterTok] = token1;
// internal while loop
while(...) {
// some code here surely not involved in the issue
} else {
if(init2 == 0) {
currEdit = config(token1,token2);
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
init2 = 1;
} else {
if((abs((int)strlen(token1)-(int)strlen(token2)))<=currEdit) {
if((tempEdit = config(token1,token2)) == currEdit) {
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
if(toPrint.index == size_arr-1) {
size_arr = size_arr*2;
toPrint.saved = realloc(toPrint.saved, size_arr);
}
} else if((tempEdit = config(token1,token2))<currEdit) {
freeArr(toPrint, size_arr);
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
currEdit = tempEdit;
}
}
}
flag = 0;
word = NULL;
temp = NULL;
freeArr(toPrint, size_arr);
}
}
editArr[counterTok] = currEdit;
init2 = 0;
totalIndex = totalIndex + toPrint.index + 1;
final = realloc(final, (sizeof(char*)*totalIndex));
uniteArr(toPrint, final, oldIndex);
oldIndex = toPrint.index;
freeArr(toPrint,size_arr);
fseek(fp2,0,SEEK_SET);
counterTok++;
}
You start with final uninitialized.
char **final;
change it to:
char **final = NULL;
Even if you are starting with no allocation, it needs a valid value (e.g. NULL) because if you don't initialize a local variable to NULL, it gets garbage, and realloc() will think it is reallocating a valid chunk of memory and will fail into Undefined Behaviour. This is probably your problem, but as you have eliminated a lot of code in between the declaration and the first usage of realloc, whe cannot guess what is happening here.
Anyway, if you have indeed initialized it, I cannot say, as you have hidden part of the code, unlistening the recommendation of How to create a Minimal, Reproducible Example
.
There are several reasons (mostly explained there) to provide a full but m inimal, out of the box, failing code. This allows us to test that code without having to provide (and probably solving, all or part) the neccesary code to make it run. If you only post a concept, you cannot expect from us complete, full running, and tested code, degrading strongly the quality of SO answers.
This means you have work to do before posting, not just eliminating what you think is not worth mentioning.
You need to build a sample that, with minimum code, shows the actual behaviour you see (a nonworking complete program) This means eliminating everything that is not related to the problem.
You need (and this is by far more important) to, before sending the code, to test it at your site, and see that it behaves as you see at home. There are many examples that, when eliminated the unrelated code, don't show the commented behaviour.
...and then, without touching anymore the code, send it as is. Many times we see code that has been touched before sending, and the problem dissapeared.
If we need to build a program, we will probably do it with many other mistakes, but not yours, and this desvirtuates the purpose of this forum.
Finally, sorry for the flame.... but it is necessary to make people read the rules.

Strcmp generate a core dump

So i have a std::unordered_map, i want to acces to strings stored intro this map. I want to search intro intro all words inside the map and compare with a given word. If the strings are same then continue execution of the if statement.
{
public:
bool CheckFoo(const char* word);
protected:
typedef std::unordered_map<std::string, bool> word_map;
word_map words_map;
};
bool CheckFoo(const char* word)
{
if (words_map.empty())
{
return false;
}
auto it = words_map.begin();
while (it != words_map.end())
{
const std::string &r = it->first;
const char* tmp = word;
if (strcmp(tmp, r.c_str() ) == 0)
{
return true;
}
}
return false;
}
if ( CheckFoo("wordFoo") )
{
// bla bla
}
The problem is that those codes generate a .core dump file..
Do you see any mistakes in my codes?
The crash core analyze point me to strcmp line
Can't write comments yet but,
Like Nunchy wrote, tmp is not defined in that context.
I also noticed that your code never increments the map iterator, which would result in a never ending loop.
I'm assuming you did not copy your actual code into your post but instead rewrote it hastily which resulted in some typos, but if not, try making sure you're using temp and not tmp in your call to strcmp, and make sure the loop actually increments the iterator.
Like one of the comments on your post points out as well, make sure you actually have data in the map, and the function parameter.
You are declaring temp then referencing tmp which doesn't exist:
const char* temp = word;
if (strcmp(tmp, r.c_str() ) == 0)
Does this compile? Surely it should be:
const char* temp = word;
if (strcmp(temp, r.c_str() ) == 0)
?

Disassembly view while debugging in Clion 2017.3.4 - what does it mean?

I'm currently using Clion 2017.3.4 in C99.
while trying to run and debug my program, the debugger jumps into 'disassembly view', and I want to know what the problem is.
basically, the function gets a season(type), a input string (season_info), and an index, that points to a different place in the input string.
the function should return the year as an integer, while the input is a string
the disassembly view is showen when I step into the free() line.
any ideas what the problem is?
and generally what the disassembly view means?
int GetSeasonYear(Season season, const char* season_info, int *index){
char* tmp_str = GetStringByLine(season_info, index);
if(tmp_str == NULL){
SeasonDestroy(season);
return 0;
}
season->season_year = atoi(tmp_str);
free(tmp_str);
return 1;
}
this is the function used inside the GetSeasonYear function(although I check and it works fine).
char* GetStringByLine(const char* season_info, int* index){ // change back to static
int i = 0;
while(season_info[i] != '\n'){
i++;
}
char* tmp_str = malloc(sizeof(char)*(i+1));
if(tmp_str == NULL){
return NULL;
}
memcpy(tmp_str, season_info, sizeof(char)*i);
tmp_str[i+1]='\0';
*index = i;
return tmp_str;
}
thanks
You are stepping into a function (free) for which you either
a) Do not have the source for
or
b) have the source for but the debuuger cannot locate it.
free() is a call to the system to release memory. It's more than likely been compiled with high optimisation and without debug symbols, so the best the debugger can do is just show you the disassembled machine code that it's executing.
Basically, it's normal. There's also very little benefit to stepping into calls like that.

Segfault thrown on one line of code

I am using this library for libgps and having a few issues with it getting it to run properly.
The error from my debugger after it says segfault is:
Cannot find bounds of current function
The line of code throwing this is located in this file, on line 132.
uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16);
I don't know the context of this at all, and I dont know why it would / wouldn't throw a segfault.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <gps.h>
#include <math.h>
/*
*
*/
int main(int argc, char** argv) {
// Open
gps_init();
gps_on();
loc_t data;
gps_location(&data);
printf("%lf %lf\n", data.latitude, data.longitude);
return (EXIT_SUCCESS);
}
The function gps_location() takes you into gps.c and from there it runs into serial.c, once it runs:
void serial_readln(char *buffer, int len)
{
char c;
char *b = buffer;
int rx_length = -1;
while(1) {
rx_length = read(uart0_filestream, (void*)(&c), 1);
if (rx_length <= 0) {
//wait for messages
sleep(1);
} else {
if (c == '\n') {
*b++ = '\0';
break;
}
*b++ = c;
}
}
}
On the break it returns to gps.c goes into:
switch (nmea_get_message_type(buffer)) {
which takes it into nmea.c for nmea_get_message_type above.
It then runs the line:
if ((checksum = nmea_valid_checksum(message)) != _EMPTY)
taking it down to: uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16); which is where the error is.
What is causing this?
Edit:
uint8_t is defined as: typedef unsigned char uint8_t;
Segmentation fault is not a "thrown exception" per se, it is a hardware-issued problem ("you said go there, but I don't see anything named 'there'").
As for your problem: what happens when strchr() does not find the specified character? I suggest you try it and find out.
The code you are working with is horrible and has no error checking anywhere. So it may go haywire for any unexpected input. This could be a potential security vulnerability too.
To fix this particular instance, change the code to:
if ( !message )
return NMEA_CHECKSUM_ERR; // possibly `exit` or something, this shouldn't happen
char *star = strchr(message, '*');
if ( !star )
return NMEA_CHECKSUM_ERR;
uint8_t checksum = strtol(star, NULL, 16);
The nmea_parse_gpgga and nmea_parse_gprmc also have multiple instances of a similar problem.
These functions might be acceptable if there was a parser or a regexp check that sanitizes the input before calling these functions. However, based on your question (I didn't check the codebase), it seems data is passed directly from read which is inexcusable.
The segfaulting function was not designed to handle an empty message or in fact any message not matching the expected form.
Another disastrous blunder is that the serial_readln function never checks that it does not write beyond len.

bilingual program in console application in C

I have been trying to implement a way to make my program bilingual : the user could chose if the program should display French or English (in my case).
I have made lots of researches and googling but I still cannot find a good example on how to do that :/
I read about gettext, but since this is for a school's project we are not allowed to use external libraries (and I must admit I have nooo idea how to make it work even though I tried !)
Someone also suggested to me the use of arrays one for each language, I could definitely make this work but I find the solution super ugly.
Another way I thought of is to have to different files, with sentences on each line and I would be able to retrieve the right line for the right language when I need to. I think I could make this work but it also doesn't seem like the most elegant solution.
At last, a friend said I could use DLL for that. I have looked up into that and it indeed seems to be one of the best ways I could find... the problem is that most resources I could find on that matter were coded for C# and C++ and I still have no idea how I would do to implement in C :/
I can grasp the idea behind it, but have no idea how to handle it in C (at all ! I do not know how to create the DLL, call it, retrieve the right stuff from it or anything >_<)
Could someone point me to some useful resources that I could use, or write a piece of code to explain the way things work or should be done ?
It would be seriously awesome !
Thanks a lot in advance !
(Btw, I use visual studio 2012 and code in C) ^^
If you can't use a third party lib then write your own one! No need for a dll.
The basic idea is the have a file for each locale witch contains a mapping (key=value) for text resources.
The name of the file could be something like
resources_<locale>.txt
where <locale> could be something like en, fr, de etc.
When your program stars it reads first the resource file for specified locale.
Preferably you will have to store each key/value pair in a simple struct.
Your read function reads all key/value pair into a hash table witch offers a very good access speed. An alternative would be to sort the array containing the key/value pairs by key and then use binary search on lookup (not the best option, but far better than iterating over all entries each time).
Then you'll have to write a function get_text witch takes as argument the key of the text resource to be looked up an return the corresponding text in as read for the specified locale. You have to handle keys witch have no mapping, the simplest way would be to return key back.
Here is some sample code (using qsort and bsearch):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define DEFAULT_LOCALE "en"
#define NULL_ARG "[NULL]"
typedef struct localized_text {
char* key;
char* value;
} localized_text_t;
localized_text_t* localized_text_resources = NULL;
int counter = 0;
char* get_text(char*);
void read_localized_text_resources(char*);
char* read_line(FILE*);
void free_localized_text_resources();
int compare_keys(const void*, const void*);
void print_localized_text_resources();
int main(int argc, char** argv)
{
argv++;
argc--;
char* locale = DEFAULT_LOCALE;
if(! *argv) {
printf("No locale provided, default to %s\n", locale);
} else {
locale = *argv;
printf("Locale provided is %s\n", locale);
}
read_localized_text_resources(locale);
printf("\n%s, %s!\n", get_text("HELLO"), get_text("WORLD"));
printf("\n%s\n", get_text("foo"));
free_localized_text_resources();
return 0;
}
char* get_text(char* key)
{
char* text = NULL_ARG;
if(key) {
text = key;
localized_text_t tmp;
tmp.key = key;
localized_text_t* result = bsearch(&tmp, localized_text_resources, counter, sizeof(localized_text_t), compare_keys);
if(result) {
text = result->value;
}
}
return text;
}
void read_localized_text_resources(char* locale)
{
if(locale) {
char localized_text_resources_file_name[64];
sprintf(localized_text_resources_file_name, "resources_%s.txt", locale);
printf("Read localized text resources from file %s\n", localized_text_resources_file_name);
FILE* localized_text_resources_file = fopen(localized_text_resources_file_name, "r");
if(! localized_text_resources_file) {
perror(localized_text_resources_file_name);
exit(1);
}
int size = 10;
localized_text_resources = malloc(size * sizeof(localized_text_t));
if(! localized_text_resources) {
perror("Unable to allocate memory for text resources");
}
char* line;
while((line = read_line(localized_text_resources_file))) {
if(strlen(line) > 0) {
if(counter == size) {
size += 10;
localized_text_resources = realloc(localized_text_resources, size * sizeof(localized_text_t));
}
localized_text_resources[counter].key = line;
while(*line != '=') {
line++;
}
*line = '\0';
line++;
localized_text_resources[counter].value = line;
counter++;
}
}
qsort(localized_text_resources, counter, sizeof(localized_text_t), compare_keys);
// print_localized_text_resources();
printf("%d text resource(s) found in file %s\n", counter, localized_text_resources_file_name);
}
}
char* read_line(FILE* p_file)
{
int len = 10, i = 0, c = 0;
char* line = NULL;
if(p_file) {
line = malloc(len * sizeof(char));
c = fgetc(p_file);
while(c != EOF) {
if(i == len) {
len += 10;
line = realloc(line, len * sizeof(char));
}
line[i++] = c;
c = fgetc(p_file);
if(c == '\n' || c == '\r') {
break;
}
}
line[i] = '\0';
while(c == '\n' || c == '\r') {
c = fgetc(p_file);
}
if(c != EOF) {
ungetc(c, p_file);
}
if(strlen(line) == 0 && c == EOF) {
free(line);
line = NULL;
}
}
return line;
}
void free_localized_text_resources()
{
if(localized_text_resources) {
while(counter--) {
free(localized_text_resources[counter].key);
}
free(localized_text_resources);
}
}
int compare_keys(const void* e1, const void* e2)
{
return strcmp(((localized_text_t*) e1)->key, ((localized_text_t*) e2)->key);
}
void print_localized_text_resources()
{
int i = 0;
for(; i < counter; i++) {
printf("Key=%s value=%s\n", localized_text_resources[i].key, localized_text_resources[i].value);
}
}
Used with the following resource files
resources_en.txt
WORLD=World
HELLO=Hello
resources_de.txt
HELLO=Hallo
WORLD=Welt
resources_fr.txt
HELLO=Hello
WORLD=Monde
run
(1) out.exe /* default */
(2) out.exe en
(3) out.exe de
(4) out.exe fr
output
(1) Hello, World!
(2) Hello, World!
(3) Hallo, Welt!
(4) Hello, Monde!
gettext is the obvious answer but it seems it's not possible in your case. Hmmm. If you really, really need a custom solution... throwing out a wild idea here...
1: Create a custom multilingual string type. The upside is that you can easily add new languages afterwards, if you want. The downside you'll see in #4.
//Terrible name, change it
typedef struct
{
char *french;
char *english;
} MyString;
2: Define your strings as needed.
MyString s;
s.french = "Bonjour!";
s.english = "Hello!";
3: Utility enum and function
enum
{
ENGLISH,
FRENCH
};
char* getLanguageString(MyString *myStr, int language)
{
switch(language)
{
case ENGLISH:
return myStr->english;
break;
case FRENCH:
return myStr->french;
break;
default:
//How you handle other values is up to you. You could decide on a default, for instance
//TODO
}
}
4: Create wrapper functions instead of using plain old C standard functions. For instance, instead of printf :
//Function should use the variable arguments and allow a custom format, too
int myPrintf(const char *format, MyString *myStr, int language, ...)
{
return printf(format, getLanguageString(myStr, language));
}
That part is the painful one : you'll need to override every function you use strings with to handle custom strings. You could also specify a global, default language variable to use when one isn't specified.
Again : gettext is much, much better. Implement this only if you really need to.
the main idea of making programs translatable is using in all places you use texts any kind of id. Then before displaying the test you get the text using the id form the appropriate language-table.
Example:
instead of writing
printf("%s","Hello world");
You write
printf("%s",myGetText(HELLO_WORLD));
Often instead of id the native-language string itself is used. e.g.:
printf("%s",myGetText("Hello world"));
Finally, the myGetText function is usually implemented as a Macro, e.g.:
printf("%s", tr("Hello world"));
This macro could be used by an external parser (like in gettext) for identifying texts to be translated in source code and store them as list in a file.
The myGetText could be implemented as follows:
std::map<std::string, std::map<std::string, std::string> > LangTextTab;
std::string GlobalVarLang="en"; //change to de for obtaining texts in German
void readLanguagesFromFile()
{
LangTextTab["de"]["Hello"]="Hallo";
LangTextTab["de"]["Bye"]="Auf Wiedersehen";
LangTextTab["en"]["Hello"]="Hello";
LangTextTab["en"]["Bye"]="Bye";
}
const char * myGetText( const char* origText )
{
return LangTextTab[GlobalVarLang][origText ].c_str();
}
Please consider the code as pseudo-code. I haven't compiled it. Many issues are still to mention: unicode, thread-safety, etc...
I hope however the example will give you the idea how to start.

Resources