I have a problem with a code I'm checking. I get a Segmentation fault (core dumped) and I think the problem is in this part of the code
The code supposed to add a new item to a connected list by users input.
The input should look like this
word_#_1999_#_synonym_#_FORIGEN
thank you in advance
// Add a new word to the dictionary with the format of { devoted_#_2003,_2001,_2008_#_worship_#_AHAVA }
struct Word * addWord(struct Word * dictionary)
{
struct Word *scan = dictionary;
struct Word *newWord = (struct Word *)malloc(sizeof(struct Word));
char *input = (char *)malloc(sizeof(char) * 128);
char *inputBackup = (char *)malloc(sizeof(char) * 128);
char *years = (char *)malloc(sizeof(char) * 128);
int count = 0;
int tempYear;
char *wordOfNewWord;
printf("Please enter a new word into dictionary\n");
scanf("%s", input);
strcpy(inputBackup, input);
// Init newWord
newWord = (struct Word *)malloc(sizeof(struct Word));
newWord->next = NULL;
newWord->numOfYears = 0;
// Check if good
if(countSubstring(input, "_#_") != 3)
{
printf("error\n");
return NULL;
}
// Get the word name
wordOfNewWord = strtok(input, "_#_");
newWord->word = (char *)malloc(sizeof(wordOfNewWord));
strcpy(newWord->word, wordOfNewWord);
// Get the word years
years = strtok(NULL, "#");
newWord->numOfYears = countSubstring(years, ",_") + 1;
newWord->years = (unsigned short *)malloc(sizeof(unsigned short) * newWord->numOfYears);
years = strtok(years, ",_");
tempYear = strtol(years, NULL, 10);
if (tempYear <= 9999 && tempYear > 0)
{
*(newWord->years + count) = tempYear;
}
else
{
printf("error\n");
return NULL;
}
count = 1;
years = strtok(NULL, ",_");
while (years != NULL)
{
tempYear = strtol(years, NULL, 10);
if (tempYear <= 9999 && tempYear > 0)
{
*(newWord->years + count) = tempYear;
}
else
{
printf("error\n");
return NULL;
}
count++;
years = strtok(NULL, ",_");
}
// Get word synonims
strcpy(input, inputBackup);
input = strtok(input, "#");
input = strtok(NULL, "#");
input = strtok(NULL, "#");
newWord->numOfSynonym = countSubstring(input, ",_") + 1;
newWord->synonymWords = (char **)malloc(sizeof(char) * 30 * newWord->numOfSynonym);
input = strtok(input, ",_");
*(newWord->synonymWords) = input;
count = 1;
input = strtok(NULL, ",_");
while (input != NULL)
{
*(newWord->synonymWords + count) = input;
count++;
input = strtok(NULL, ",_");
}
// Get translation
input = (char *)malloc(sizeof(char) * 120);
strcpy(input, inputBackup);
input = strtok(input, "#");
input = strtok(NULL, "#");
input = strtok(NULL, "#");
input = strtok(NULL, "#");
newWord->numOfTrans = countSubstring(input, ",_") + 1;
newWord->tranWords = (char **)malloc(sizeof(char) * 30 * newWord->numOfTrans);
input = strtok(input, ",_");
*(newWord->tranWords) = input;
count = 1;
input = strtok(NULL, ",_");
while (input != NULL)
{
*(newWord->tranWords + count) = input;
count++;
input = strtok(NULL, ",_");
}
// Put the new word in the dictionary
if(findWord(dictionary, newWord->word) == 1)
{
printf("error\n");
return NULL;
}
}
there is the struct
struct Word
{
char *word;
unsigned short * years;
unsigned short numOfYears;
char ** synonymWords;
unsigned short numOfSynonym;
char ** tranWords;
unsigned short numOfTrans;
struct Word *next;
};
For a kickoff, this code doesn't make much sense:
if (tempYear <= 9999 && tempYear > 0)
{
*(newWord->years + count) = tempYear;
}
considering the only time count is used prior to this line is: int count = 0;
Other than that, you seem to be oblivious to the fact that char ** and char * are not the same thing!:
newWord->synonymWords = (char **)malloc(sizeof(char) * 30 * newWord->numOfSynonym);
//and
newWord->tranWords = (char **)malloc(sizeof(char) * 30 * newWord->numOfTrans);
Which are allocating char *, but at the same time, you're doing:
char *wordOfNewWord;
newWord->word = (char *)malloc(sizeof(wordOfNewWord));
Which is actually allocating memory to hold a pointer, depending on the architecture (32 or 64 bits) a pointer generally requires 4 to 8 times as much memory as a char, of which the size is by definition 1.
Please allocate memory according to the suggestions made in the comments:
char **pointers_to_strings = malloc(10*sizeof(*pointers_to_strings));
for(int i=0;i<10;++i)
pointers_to_strings[i] = calloc(101, sizeof(*pointers_to_strings[i]));
To ensure you're always allocating the right amount of memory, required to accomodate whatever type it will hold.
And of course, no malloc or calloc without a free call:
for (int i=0;i<10;++i)
{
free(pointers_to_strings[i]);
pointers_to_strings[i] = NULL;
}
free(pointers_to_strings);
pointers_to_strings = NULL;
the problem is in this lines
char *wordOfNewWord;
newWord->word = (char *)malloc(sizeof(wordOfNewWord));
strcpy(newWord->word, wordOfNewWord);
Related
Let's assume I have a char buffer with data separated with char ":";
char pt[256] = "pt:ct:mac";
char *plain_text;
char *cipher_text;
char *mac;
char *next = NULL;
char *tokens = NULL;
const char sep[2] = ":";
tokens = strtok_r(pt, sep, &next);
do
{
if(i == 0)
{
int ln = strlen(tokens);
plain_text = (char*)malloc(ln * 1);
i++;
continue;
}
if(i == 1)
{
int ln = strlen(tokens);
cipher_text = (char*)malloc(ln * 1);
i++;
continue;
}
if(i == 2)
{
int ln = strlen(tokens);
mac = (char*)malloc(ln * 1);
i++;
continue;
}
}
while((tokens = strtok_r(NULL, sep, &next)) != NULL);
free(plain_text);
free(cipher_text);
free(mac);
, so the question is how in the right way to deal with strtok_r output results.
Basically, the main aim is to get the results out of pt string, and put it in the dynamic containers. Since, I don't know the size of plain_text and cipher_text.
Is it the right way to program it?
Apart from that, if do see some minor mistakes or something can be written with better practices please do let me know ;) Thank you!
I would do it with array of pointers.
char pt[256] = "pt:ct:mac";
char *next = NULL;
char *token = NULL;
char *tokens[3] = {NULL};
const char sep[2] = ":";
token = strtok_r(pt, sep, &next);
while(token)
{
int ln = strlen(token);
tokens[i]= (char*)malloc((ln * sizeof(char)) + 1);
strcpy(tokens[i],token);
i++;
token = strtok_r(NULL, sep, &next);
}
for (int i = 0; i< 3 && tokens[i]; i++) {
free(tokens[i]);
tokens[i] = NULL;
}
I have been trying to write a function that takes in strings as a line and returns a pointer to an array of words. The function written below does something similar
How can I rewrite the following code1 but it should be better than code2 by being able to change the delimiter. However, code1 works but during memory allocation the same memory is duplicated for the words array. Thereby causing word duplication.
Code 1:
char *split(const char *string) {
char *words[MAX_LENGTH / 2];
char *word = (char *)calloc(MAX_WORD, sizeof(char));
memset(word, ' ', sizeof(char));
static int index = 0;
int line_index = 0;
int word_index = 0;
while (string[line_index] != '\n') {
const char c = string[line_index];
if (c == ' ') {
word[word_index+ 1] = '\0';
memcpy(words + index, &word, sizeof(word));
index += 1;
if (word != NULL) {
free(word);
char *word = (char *)calloc(MAX_WORD, sizeof(char));
memset(word, ' ', sizeof(char));
}
++line_index;
word_index = 0;
continue;
}
if (c == '\t')
continue;
if (c == '.')
continue;
if (c == ',')
continue;
word[word_index] = c;
++word_index;
++line_index;
}
index = 0;
if (word != NULL) {
free(word);
}
return *words;
}
Code 2:
char **split(char *string) {
static char *words[MAX_LENGTH / 2];
static int index = 0;
// resetting words
for (int i = 0; i < sizeof(words) / sizeof(words[0]); i++) {
words[i] = NULL;
}
const char *delimiter = " ";
char *ptr = strtok(string, delimiter);
while (ptr != NULL) {
words[index] = ptr;
ptr = strtok(NULL, delimiter);
++index;
}
index = 0;
return words;
}
However I noticed that the memory of word+index is been reassigned to the same location thereby causing word duplication.
strtok() always returns a different pointer into the initial string. This cannot produce duplicates, unless you call it twice with the same input string (maybe with new contents).
However, your function returns a pointer to a static array, which is overwritten on each call to split(), voiding the results of all previous calls. To prevent this,
either allocate new memory in each call (which must be freed by the caller):
char *words = calloc(MAX_LENGTH / 2, 1);
or return a struct instead (which is always copied by value):
struct wordlist { char *word[MAX_LENGTH / 2]; };
wordlist split(char *string)
{
wordlist list = {};
/* ... */
list.word[index] = /* ... */;
/* ... */
return list;
}
bellow is the code:
from some reason the calloc inside the while loop, is failing on the second iteration.
it looks the heap is corupted (not sure) but not clear the root cause.
please also take a look on the comment added there.
appriciate fast response.
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include<stdio.h>
#include <stdlib.h>
struct User_
{
char* id;
char* firstName;
char* lastName;
int age;
char gender[2];
char* userName;
char* password;
char* description;
char hobbies[2];
}typedef User;
void replaceEnterInString(int lengthString, char* string, int maxChars);
int main()
{
char str1[500] = "012345678;danny;cohen;22;M;danny1993;123;1,2,4,8;Nice person";
char str2[500] = "223325222;or;dan;25;M;ordan10;1234;3,5,6,7;Singer and dancer";
int j = 0;
char *token = NULL, arrangingHobbies;
int lengthStr, tempAge, hobby[4], i;
while(j<2)
{
User* newUser = NULL;
here it pass on first time but fail on second time. but only when adding the code that map the token to the newUser. without the mapping - do manage to calloc the user again and again as much as needed
error code: Critical error detected c0000374 - TEST.exe has triggered a breakpoint.
newUser = (User*)calloc(1, sizeof(User));
if (newUser == NULL)
{
printf("error");
exit(1);
}
//start map string to user
if (j == 0)
{
token = strtok(str1, ";");
printf("%s", str1);
}
else {
token = strtok(str2, ";");
printf("%s", str2);
}
//Input ID
newUser->id = (char*)calloc(10, sizeof(char));
if (newUser->id == NULL)
{
printf("error");
exit(1);
}
strcpy(newUser->id, token);
//Input first name
token = strtok(NULL, ";");
lengthStr = strlen(token);
newUser->firstName = (char*)calloc((lengthStr + 1), sizeof(char));
if (newUser->firstName == NULL)
{
printf("error");
exit(1);
}
strcpy(newUser->firstName, token);
//Input last name
token = strtok(NULL, ",;");
lengthStr = strlen(token);
newUser->lastName = (char*)calloc((lengthStr + 1), sizeof(char));
if (newUser->lastName == NULL)
{
printf("error");
exit(1);
}
strcpy(newUser->lastName, token);
//Input Age
token = strtok(NULL, ",;");
tempAge = atoi(token);
newUser->age = tempAge;
//Input gender
token = strtok(NULL, ",;");
newUser->gender[0] = token[0];
//Input User Name
token = strtok(NULL, ",;");
lengthStr = strlen(token);
newUser->userName = (char*)calloc((lengthStr), sizeof(char));
if (newUser->userName == NULL)
{
printf("error");
exit(1);
}
strcpy(newUser->userName, token);
//Input password
token = strtok(NULL, ",;");
lengthStr = strlen(token);
newUser->password = (char*)calloc((lengthStr), sizeof(char));
if (newUser->password == NULL)
{
printf("error");
exit(1);
}
strcpy(newUser->password, token);
//Input hobbies
newUser->hobbies[0] = 0;
for (i = 0; i < 4; ++i)
{
token = strtok(NULL, ",;");
tempAge = atoi(token);
arrangingHobbies = 1;
arrangingHobbies <<= (tempAge - 1);
newUser->hobbies[0] |= arrangingHobbies;
}
//Input description
token = strtok(NULL, ",;");
newUser->description = (char*)calloc((lengthStr), sizeof(char));
if (newUser->description == NULL)
{
printf("error");
exit(1);
}
replaceEnterInString(strlen(token), token, 300);
strcpy(newUser->description, token);
j++;
}
}
void replaceEnterInString(int lengthString, char* string, int maxChars)
{
if (lengthString < maxChars)
{
//remove the /n
string[lengthString - 1] = '\0';
}
}
Maybe there are other issues as well, yet the following code leads to undefined behaviour for sure:
lengthStr = strlen(token);
newUser->userName = (char*)calloc((lengthStr), sizeof(char));
...
strcpy(newUser->userName, token);
In previous similar statements, you correctly wrote ... = (char*)calloc((lengthStr+1), sizeof(char));.
BTW: In C, you usually don't cast the results of malloc, sizeof(char) is always 1 by definition, and there is no need for setting memory to 0 using calloc if you fill the memory with a subsequent strcpy anyway. So you should write...
lengthStr = strlen(token);
newUser->userName = malloc(lengthStr+1);
...
strcpy(newUser->userName, token);
Look through your code for similar issues, please.
I am trying to figure out how to get my array of strings from get_arguments to NULL terminate, or if that isn't the issue to function in my execv call.
char ** get_arguments(const char * string) {
char * copy = strdup(string);
char * remove_newline = "";
for(;;) {
remove_newline = strpbrk(copy, "\n\t");
if (remove_newline) {
strcpy(remove_newline, "");
}
else {
break;
}
}
char (* temp)[16] = (char *) malloc(256 * sizeof(char));
char * token = strtok(copy, " ");
strcpy(temp[0], token);
int i = 1;
while (token && (token = strtok(NULL, " "))) {
strcpy(temp[i], token);
i++;
}
char * new_null;
//new_null = NULL;
//strcpy(temp[i], new_null);
if(!temp[i]) printf("yup\n");
int c = 0;
for ( ; c <= i; c++) {
printf("%s ", temp[c]);
}
return temp;
}
I am trying to read in a string, space separated, similar to find ./ -name *.h. I am trying to input them into execv.
char (* arguments)[16] = (char **) malloc(256 * sizeof(char));
//...numerous lines of unrelated code
pid = fork();
if (pid == 0) {
arguments = get_arguments(input_string);
char * para[] = {"find", "./","-name", "*.h", NULL};
execv("/usr/bin/find", (char * const *) arguments);
//printf("%s\n", arguments[0]);
printf("\nexec failed: %s\n", strerror(errno)); //ls -l -R
exit(-1);
}
When I swap arguments in the execv call for para it works as intended, but trying to call with arguments returns exec failed: Bad address. If I remove the NULL from para I get the same issue. I've tried strcpy(temp, (char *) NULL), the version you see commented out in get_arguments, and a number of other things that I can't recall in their entirety, and my program ranges from Segmentation fault to failure to compile from attempting to strcpy NULL.
Changing the declarations of arguments and temp to char ** arguments = (char *) malloc(256 * sizeof(char)); ``char ** temp = (char *) malloc(256 * sizeof(char));clears upwarning: initialization from incompatible pointer typebut causes segfault on all calls toget_arguments`.
You want this:
char* temp[256]; // an array of 256 char*'s
char * token = strtok(copy, " ");
temp[0] = strdup(token);
int i = 1;
while (token && (token = strtok(NULL, " "))) {
temp[i] = strdup(token);
i++;
}
temp[i] = NULL;
I have such a structure:
typedef struct kodProgramu {
char* etykieta;
char* instrukcja;
char* operand;
struct kodProgramu *nast;
} kodPrg;
This code is for adding new element:
void pobierzKodStdin(kodPrg *kod, char *wynik, char *linia, int flagaEtyk)
{
wynik = fgets(linia, 80, stdin);
while(wynik != NULL)
{
kodPrg *wsk, *nowy;
wsk = kod;
while(wsk->nast != NULL)
wsk = wsk->nast;
if(linia[0] == ' ')
flagaEtyk = 1;
nowy = (kodPrg*)malloc(sizeof(kodPrg));
int licznik = 0;
char *pch;
pch = strtok(linia, ":# ");
while(pch != NULL)
{
if(flagaEtyk == 0)
{
if(licznik == 0)
nowy->etykieta = pch;
else if(licznik == 1)
nowy->instrukcja = pch;
else if(licznik == 2)
nowy->operand = pch;
}
if(flagaEtyk == 1)
{
if(licznik == 0)
nowy->instrukcja = pch;
else if(licznik == 1)
nowy->operand = pch;
}
licznik++;
pch = strtok(NULL, ":# ");
}
nowy->nast = NULL;
wsk->nast = nowy;
flagaEtyk = 0;
wynik = fgets(linia, 80, stdin);
}
}
This function print this structure to the console:
void wypiszKod(kodPrg *kod)
{
kodPrg *wsk = kod;
while(wsk != NULL)
{
printf("%s %s %s\n", wsk->etykieta, wsk->instrukcja, wsk->operand);
wsk = wsk->nast;
}
}
This is my main function:
int main()
{
char linia[80], *wynik;
char *wsk = malloc(sizeof(char));
int flagaEtyk = 0;
//tasmaWejsc *wejscie = (tasmaWejsc*)malloc(sizeof(tasmaWejsc));
//tasmaWyjsc *wyjscie = (tasmaWyjsc*)malloc(sizeof(tasmaWyjsc));
//wyjscie->wartosc = 0;
//wyjscie->nast = NULL;
kodPrg *kod = (kodPrg*)malloc(sizeof(kodPrg));
kod->etykieta = " ";
kod->instrukcja = " ";
kod->operand = " ";
kod->nast = NULL;
int liczba;
//wprowadzWejscie(wynik, linia, wejscie);
//wypiszWejscie(wejscie);
//system("cls");
pobierzKodStdin(kod, wynik, linia, flagaEtyk);
wypiszKod(kod);
return 0;
}
Now, when I enter one line like : test test test
It's working good and print test test test in console.
But when I enter more lines, for example:
test test test
xxxx xxxx xxxx
The program is printing:
xxxx xxxx xxxx
xxxx xxxx xxxx
It's like the second line replace the first one.
I don't know why, when I have a struct with int instead of char * it's working good. Next element are added and it' printing good, but when char * it's working as I described above.
How to add new elemnt to the list when I have struct with char *?
I think you should realize that strtok works on a static buffer
So when you write like this
pch = strtok(linia, ":# ");
while(pch != NULL)
{
if(flagaEtyk == 0)
{
if(licznik == 0)
nowy->etykieta = pch;
you are assigning the pointer in your shiny heap element to a string that will disappear by the next line (linia).
wynik = fgets(linia, 80, stdin);
what you need to do is to make a copy of the string, this can be done using strdup()
nowy->etykieta = strdup(pch);
Every string in your linked list is mapped to portions of linia[80], which is overwritten at each line access.
Some strdup() calls should solve your issue.