I don't manage to copy a string in my function. Once I try to print the strings, nothing appears.
int read_exit_tr (){
char * buff = (char *) malloc (20 * sizeof(char));
//char * temp;
int r = read(0,buff,SIZE_LECTURE);
//temp = (char *) malloc (strlen(buff) + 1 );
//memcpy(buff,temp,20);
if (r > 0) {
printf("%s X\n",buff);
//printf("%s X\n",temp);
}else
printf("erreur");
free(buff);
// free(temp);
return 0;
}
In this version, buff is printed correctly. But once I uncomment the lines and print buff and temp, both are empty.
Thanks for reading, could you please help me?
Related
I'm trying to make a program to crack passwords by searching through a file of md5 hashes and using bsearch to find them in a rockyou database. My problem is that I'm running into a segmentation fault that is either caused by my qsort or my printf (I've run Valgrind and it says printf, but manipulating qsort changes the error output). I can't seem to find the solution online, though I've tried flushing stdout and different ways to size the array in the qsort function.
char **dict = read_dict( argv[2] );
read_dict, which I haven't placed here because it's a hefty chunk of code, takes in the dictionary file, splits it into an array of strings, formats it into hash:password, and mallocs the space for it. It then returns the pointer of the array of pointers that contains each string.
int qcompare( const void *a, const void *b)
{
return strncmp( *((char **)a), *((char **)b), HASH_LEN);
}
qsort(dict, (sizeof(dict) / sizeof(dict[0])), sizeof(char *), qcompare);
for (int i = 0; dict[i] != NULL; i++)
{
printf("%s\n", dict[i]);
}
The printf shown here isn't the actual one I'm using, it's just a simpler one I was trying to use to debug my code. It's my first time posting so hopefully I haven't done anything atrociously wrong with formatting this question. Thank you in advance for any help I get.
read_dict as requested
char **read_dict(char *filename)
{
FILE *f = fopen(filename, "r");
if (!f)
{
printf("read_dict: file error message\n");
exit(1);
}
int arrlen = 0;
int i = 0;
char **dict = NULL;
char buf[PASS_LEN];
while (fgets(buf, PASS_LEN, f) != NULL)
{
if (i == arrlen)
{
arrlen += STEPSIZE;
char **newdict = realloc(dict, arrlen * sizeof(char*));
if (!newdict)
{
printf("read_dict: newdict error message\n");
exit(1);
}
dict = newdict;
}// end of if
buf[strlen(buf) - 1] = '\0';
int slen = strlen(buf);
char *pass = malloc( (slen + 1) * sizeof(char));
strcpy(pass, buf);
char output[(HASH_LEN + PASS_LEN + 1)];
sprintf(output, "%s:%s", md5(pass, strlen(pass)), pass );
dict[i] = output;
i++;
}// end of while
if (i == arrlen)
{
char **newarr = realloc(dict, (arrlen + 1) * sizeof(char*));
if (!newarr)
{
printf("read_dict: newarr error message\n");
exit(1);
}
dict = newarr;
}
dict[i] = NULL;
return dict;
}// end of read_dict
I'm having a little trouble understanding where my code goes wrong. I want to store into an array of strings multiple lines and after to display them; for some unknown reason after I enter a different number of lines ( let's say 5 ), it will only display the last line 5 times. Any idea?
Thank you
#include <stdio.h>
#include <string.h>
int readLine(char line[], int max);
void printLines(char *lines[], int size);
int main(){
char *lines[100];
char line[100];
int i = 0;
int len = 0;
char *p;
while( (len = readline(line,100)) > 0){
if((p = malloc(len * sizeof(char))) != NULL){
p = line;
lines[i++] = p;
}
}
lines[i] = '\0';
printLines(lines, i);
return 0;
}
int readline(char line[], int max){
if(fgets(line,max,stdin) == NULL)
return 0;
printf("%d \n", strlen(line));
return strlen(line);
}
void printLines(char *lines[], int size){
int i;
for(i = 0; i < size; i++)
printf("%s\n", lines[i]);
}
if((p = malloc(len * sizeof(char))) != NULL){
p = line;
lines[i++] = p;
You allocate memory for a string, and store the pointer returned from malloc() in p. Then you store a pointer to line in p, effectively throwing away the pointer to the memory you just allocated. You need to copy the string by using strcpy() or similar.
strcpy (p, line);
This is your problem:
if((p = malloc(len * sizeof(char))) != NULL){
p = line;
lines[i++] = p;
}
p is a pointer that points to allocated storage first, but then its value is overwritten with the value of line. What you want is to copy what is currently stored at the location that line points to to the location where p points to. The function for that is strcpy().
Notes:
sizeof (char) is by the very definition of sizeof exactly 1.
You will have buffer overflow issues (google that term!) if people enter lines longer than 100 chars.
You are not really handling malloc() failure but merely skipping some code and otherwise ignoring it. Write an error message and call exit() for now if malloc() fails. Wrap that in a function for easier reuse (ofter called xalloc()).
I have to dynamically allocate a pointer inside a while.
char * allocationg_memory(char [] path p) {
char message[4000];
char c;
unsigned int i = 0;
unsigned int count;
FILE *f;
//open the file
f = fopen(p, "rt");
count = 0;
//copy the contain of the file in message
if (f) {
while ((c = getc(f)) != EOF) {
count++;
message[i] = c;
i++;
}
fclose(f);
}
//allocating the memory
char *str = (char *) malloc(sizeof (char) * (count));
if (str == NULL) {
printf("error allocating memory for string\n");
exit(1);
}
//copy the message
strncpy (str, message, count);
return str;
}
void main {
char * ptr;
do {
//my path dynamically changing
path = path_of_file;
ptr = allocating_memory(path);
printf("%s", ptr);
free(ptr);
} while (1);
}
If I set ptr = NULL it gives me segmentation fault, if I don't, if the next print is bigger than the previus, the 2nd is printed over the 1st. What's wrong with my code?
For starters:
Your initial allocation is for 0 bytes.
You are trying to print what you have allocated as if it were a string.
Your loop never ends.
This works for me. Hopefully it helps
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char * allocating_memory(int c) {
char *str = malloc ( c + 1); // allow an extra for the null
strncpy ( str, "abcdefghijklmnopqustuvwxyx", c);
str[c] = '\0'; // make sure the string is null terminated
return str;
}
int main () {
char * ptr;
int counter = 2;
do {
ptr = NULL;
ptr = allocating_memory(counter);
printf("%s\n", ptr);
free(ptr);
counter++;
} while (counter < 27);
return 0;
}
I have to dynamically allocate array of words. Words are stored in a file separated by variable count of white-space characters. I don't know how many words is in the file a they can have variable length.
I have this code:
void readWord(FILE* stream, char *word, char first_c) {
word[0] = first_c;
char val;
int wlen = 1;
// isWhitespac is my function - tests if char is blank or '\n'
while ((val = fgetc(stream)) != EOF && isWhitespace(val) == 0) {
wlen++;
word = realloc(word, (wlen+1) * sizeof (char));
word[wlen-1] = val;
}
word[wlen] = '\0';
}
int readList(const char *file) {
FILE* f;
char **arr;
char val;
int wcount = 0;
arr = malloc(sizeof (char*));
f = fopen(file, "r");
while (fscanf(f, " %c", &val) == 1) {
wcount++;
arr = realloc(arr, wcount * sizeof (char *));
arr[wcount - 1] = malloc(sizeof (char));
readWord(f, arr[wcount-1], val);
printf("%s\n", arr[wcount-1]);
}
for (int i = 0; i < wcount; ++i) {
free(arr[i]);
}
free(arr);
fclose(f);
return 0;
}
It appears to work fine, it reads a prints all the words. But when I run the program with Valgrind the are too many errors, which I can't find. Could anyone help me? (I know I have to test if malloc and others went fine, it is just a test func.)
The Valgrind log is quite long, should I post it too?
One of the issues is that you do realloc inside readWord. If realloc allocates a new buffer and doesn't just extend the current one then your code will crash (you will double free the pointer) and this is what Valgrind picks up. To fix this I would rewrite the code so it returns a pointer instead of void.
char * readWord(FILE* stream, char *word, char first_c) {
word[0] = first_c;
char val;
int wlen = 1;
// isWhitespac is my function - tests if char is blank or '\n'
while ((val = fgetc(stream)) != EOF && isWhitespace(val) == 0) {
wlen++;
word = realloc(word, (wlen+1) * sizeof (char));
word[wlen-1] = val;
}
word[wlen] = '\0';
return word;
}
And then change the loop in readList to this:
while (fscanf(f, " %c", &val) == 1) {
wcount++;
arr = realloc(arr, wcount * sizeof (char *));
arr[wcount-1]=malloc(sizeof(char));
arr[wcount - 1] = readWord(f, arr[wcount-1], val);
printf("%s\n", arr[wcount-1]);
}
I am trying to read in from stdin (passing in value from a file). I am reading each character from the string and storing it into a dynamically allocated string pointer. When needed I realloc the memory. I am trying to get as many characters as possible. Though I can limit it to 100,000 chars. But the realloc fails after some iteration. But if I specify a chunk size big, say 1048567 during the first initialization in malloc, I am able to read the string completely. Why is this?
Below is my program:
#include <stdio.h>
#include <stdlib.h>
int display_mem_alloc_error();
enum {
CHUNK_SIZE = 31 //31 fails. But 1048567 passes.
};
int display_mem_alloc_error() {
fprintf(stderr, "\nError allocating memory");
exit(1);
}
int main(int argc, char **argv) {
int numStr; //number of input strings
int curSize = CHUNK_SIZE; //currently allocated chunk size
int i = 0; //counter
int len = 0; //length of the current string
int c; //will contain a character
char *str = NULL; //will contain the input string
char *str_cp = NULL; //will point to str
char *str_tmp = NULL; //used for realloc
str = malloc(sizeof(*str) * CHUNK_SIZE);
if (str == NULL) {
display_mem_alloc_error();
}
str_cp = str; //store the reference to the allocated memory
scanf("%d\n", &numStr); //get the number of input strings
while (i != numStr) {
if (i >= 1) { //reset
str = str_cp;
len = 0;
curSize = CHUNK_SIZE;
}
c = getchar();
while (c != '\n' && c != '\r') {
*str = (char *) c;
//printf("\nlen: %d -> *str: %c", len, *str);
str = str + 1;
len = len + 1;
*str = '\0';
c = getchar();
if (curSize / len == 1) {
curSize = curSize + CHUNK_SIZE;
//printf("\nlen: %d", len);
printf("\n%d \n", curSize); //NB: If I comment this then the program simply exits. No message is displayed.
str_tmp = realloc(str_cp, sizeof(*str_cp) * curSize);
if (str_tmp == NULL) {
display_mem_alloc_error();
}
//printf("\nstr_tmp: %d", str_tmp);
//printf("\nstr: %d", str);
//printf("\nstr_cp: %d\n", str_cp);
str_cp = str_tmp;
str_tmp = NULL;
}
}
i = i + 1;
printf("\nlen: %d", len);
//printf("\nEntered string: %s\n", str_cp);
}
str = str_cp;
free(str_cp);
free(str);
str_cp = NULL;
str = NULL;
return 0;
}
Thanks.
When you realloc
str_tmp = realloc(str_cp, sizeof(*str_cp) * curSize);
if (str_tmp == NULL) {
display_mem_alloc_error();
}
//printf("\nstr_tmp: %d", str_tmp);
//printf("\nstr: %d", str);
//printf("\nstr_cp: %d\n", str_cp);
str_cp = str_tmp;
str_tmp = NULL;
you let str_cp point to the new block of memory, but str still points into the old, now freed block. Thus when you access what str points to in the next iteration, you invoke undefined behaviour.
You need to save the offset of str with respect to str_cp, and after the reallocation, letstr point into the new block at its old offset.
And *str = (char *) c; is wrong, although there is a nonzero chance of it being functionally equivalent to the correct *str = c;.
*str = (char *) c;
This line is wrong.
str is a pointer to char and *str is a char but you are assigning a pointer to char to a char. This cannot be done in C.
Moreover:
scanf("%d\n", &numStr);
The \n in scanf call probably does not what you expect:
http://c-faq.com/stdio/scanfhang.html
And also:
str = str_cp;
free(str_cp);
free(str);
You have a double free here. After the assignment str and str_cp will have the same value so doing:
free(str_cp);
free(str);
is as if you do:
free(str);
free(str);
which is undefined behavior (you cannot free twice).