Segmentation fault when initializing pointer to char array - c

I am trying to write a program that reads text from a file, converts the characters to uppercase and then writes the output on a new file. The code works just fine for the reading and converting to uppercase parts, but for the writing the output part when I create a char* for the name of the output file, I get a segmentation fault.
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
void lowerToUpper(char* temp)
{
char* name;
name = strtok(temp,":");
// Convert to upper case
char* s = name;
while (*s)
{
*s = toupper((unsigned char) *s);
s++;
}
}
int main()
{
int fd;
char* file_name_read = "./test.txt";
fd = open(file_name_read, O_RDONLY);
char* buf_rd;
ssize_t nr;
size_t byte_count = 1000;
off_t offset = 0;
nr = pread(fd, buf_rd, byte_count, offset);
close(fd);
lowerToUpper(buf_rd);
char* file_name_write = "./test_uppercase.txt";
/* CODE FOR WRITING TO THE FILE */
return 0;
}
When I remove the char* file_name_write line, the code works fine. When I include it in the code, I get a segmentation fault.
I have tried
removing the call to the lowerToUpper() inside main
using char file_name_write[] instead of char* file_name_write
using malloc() to allocate space and then assign its value
using different byte_count and offset values
Edit:
The problem was an uninitialized pointer with buf_rd. When I added
char* buf_rd = (char*) malloc(1000 * sizeof(char));
it solved the problem.
Thank you Mr Lister and lurker!

char* buf_rd;
...
nr = pread(fd, buf_rd, byte_count, offset);
You did not allocate memory for buf_rd. It is just a pointer.

You use buf_rd as buffer, but that variable is only declared and never initialized.
The documentation says:
ssize_t pread(int fd , void * buf , size_t count , off_t offset );
pread() reads up to count bytes from file descriptor fd at offset
offset (from the start of the file) into the buffer starting at buf.
The file offset is not changed.
It is expected of you to initialize the a buffer that can be used by the pread function.

Related

How to read from pipe into a file?

I would like to read from the pipe straight into a file with the code below. base_fd is a pipe.
FILE* fp = fopen("dec_data", "wb+");
int r_result;
int len = msg_length-part-3; //set to 75933
while ((r_result = read(base_fd[0], fp, len))) {
printf("r_result: %d \n", r_result);
len -= r_result;
}
The read seems to happen fine, with r_result showing 65536 and then 10397 as required. However, when I inspect the file I created, it has a size of 0 bytes...
You have a semantic error in your code.
Take a look at the read(2) system call signature:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
The second parameter to the function is a void pointer (void *buf), which is where read will store the count bytes it reads from fd descriptor.
However, a FILE * is an abstraction of the C library. In this answer you can see more of it. The struct FILE in MinGW32 5.1.4 is:
typedef struct _iobuf
{
char* _ptr;
int _cnt;
char* _base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char* _tmpfname;
} FILE;
What read will do is similar to how we copy strings. Consider this function:
void strcpy(char *dst, char *src)
{
while(*src) *dst++ = *src++;
}
This function will copy the contents from src into dst until it finds a NULL terminating byte. This is obviously a very flawed function and should never be used, but illustrates why your example doesn't work.
Under the hood, what read is doing is very similar to this strcpy function: it is overwriting a lot of bytes in memory starting at the address pointed to by the fp pointer. You are effectively losing your reference to the FILE * pointer and the resources associated to it.
I'll bet that if you try to close(fp) after that loop you'll get a segmentation fault (it's Undefined Behavior, but I'll bet anyway).
The right way to do what you want is:
FILE* fp = fopen("dec_data", "wb+");
char *buf;
int r_result;
int len = msg_length - part - 3; //set to 75933
buf = malloc(len);
if(!buf) {
perror("malloc");
exit(EXIT_FAILURE);
}
while ((r_result = read(base_fd[0], buf, len))) {
fprintf(fp, buf);
len -= r_result;
}
free(buf);
close(fp); // now it closes the file pointer

C Pointer of array of strings garbled when retreived later

I have read a lot of the answers on the theoretical issues with memory allocation to pointer to arrays, but have not been able to fix my code...so turning to you.
I have an array of strings in a STRUCT, which I need to write to and read from. Declared as:
typedef struct client_mod
{
/* Client ad_file */
char *ad_filenames[10];
/* Client's current ad array index*/
unsigned int ad_index;
} client;
Then , inside a function , I assign values to pointer:
static int get_spots (client_mod *client)
{
char buf[512];
FILE *ptr;
if ((ptr = popen("php /media/cdn/getspot.php", "r")) != NULL) {
/* Read one byte at a time, up to BUFSIZ - 1 bytes, the last byte will be used for null termination. */
size_t byte_count = fread(buf, 1, 512 - 1, ptr);
/* Apply null termination so that the read bytes can be treated as a string. */
buf[byte_count] = 0;
}
(void) pclose(ptr);
// parse extracted string here...
int i = 0;
client->ad_filenames[i] = strdup(strtok(buf,"|"));
while(client->ad_filenames[i]!= NULL && i<5)
{
client->ad_filenames[++i] = strdup(strtok(NULL,"|"));
if (client->ad_filenames[i] != NULL && strlen(client->ad_filenames[i]) > 5) {
LOG("TESTING FOR CORRECT FILE NAMES %s\n", client->ad_filenames[i]);
}
}
}
The problem comes when I retreive the values later:
/* in looping code block */
LOG("Checking file under index = %d, file is %s", client->ad_index, client->ad_filenames[client->ad_index]);
The first two members of the array are retreived normally, everything after that is garbled.
I would appreciate any guidance. Thanks!
I understand this probablby comes from undefined behaviour of assigning directly to the pointer, but I can't figure out how to solve it.
I think the problem is with assigning to this struct element.
char *ad_filenames[10];
ad_filenames is an array of 10 of pointer to characters.
What that means is that memory allocation is needed for each index.
Something like
client->ad_filenames[0] = strdup(var1);
strdup() does both malloc() and strcpy() within this function.
client should be a variable name. You already defined client as a type.
Here is working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct client_mod
{
/* Client ad_file */
char *ad_filenames[10];
/* Client's current ad array index*/
unsigned int ad_index;
}CLIENT1;
CLIENT1 *client;
int func( char *var1 ) {
client->ad_filenames[0] = strdup(var1);
}
int
main(void)
{
char str1[10];
client = malloc( sizeof client );
strcpy( str1, "Hello" );
func( str1 );
printf("%s\n", client->ad_filenames[0] );
free(client->ad_filenames[0]);
free (client);
}
Your problem is with the line,
size_t byte_count = fread(buf, 1, 1000 - 1, ptr);
Read the man fread page,
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
you read 1000-1 members of size 1 into buf, which is only allocated buf[512], either expand buf or decrease fread 3rd argument,
buf[1000+1];
size_t byte_count = fread(buf, 1, sizeof(buf)-1, ptr);

Assigning a char array to a char*

I'm trying to write a function that prefixes a string with its length. I can't seem to assign a char[] to a char *. Mysteriously, if I print out some debugging code before the assignment, it works.
char *prefixMsgWLength(char *msg){
char *msgWLength;
int msgLength = strlen(msg);
if (msgLength == 0){
msgWLength = "2|";
}
else{
int nDigits = floor(log10(abs(msgLength))) + 1;
int nDigits2 = floor(log10(abs(msgLength + nDigits + 1))) + 1;
if (nDigits2 > nDigits){
nDigits = nDigits2;
}
msgLength += nDigits + 1;
char prefix[msgLength];
sprintf(prefix, "%d|", msgLength);
strcat(prefix, msg);
// if I uncomment the below, msgWLength is returned correctly
// printf("msg: %s\n", prefix);
msgWLength = prefix;
}
return msgWLength;
}
The problem in your code is
msgWLength = prefix;
here, you're assigning the address of a local variable (prefix) to the pointer and you try to return it.
Once the function finishes execution, the local variables will go out of scope and the returned pointer will be invalid.
You need to make prefix as a pointer and allocate memory dynamically, if you want it to retain it's existence after returning from the function.
String reallocation to the exact length can be very cumbersome in C. You'd probably be much better off just using a sufficiently large buffer. Here, I use limits.h to determine the size of a line buffer according to the system (LINE_MAX):
#include <stdio.h>
#include <limits.h>
#include <string.h>
int main()
{
/* Our message */
char const msg[] = "Hello, world!";
/* Buffer to hold the result */
char buffer[LINE_MAX];
/* Prefix msg with length */
snprintf(buffer, LINE_MAX, "%lu|%s", strlen(msg)+1, msg);
/* Print result */
printf("%s\n", buffer);
return 0;
}

Am I freeing memory properly in this C program?

I'm writing a small program that reads multiple input lines from the user:
#include <stdio.h>
#include <stdlib.h>
#define MAXINPUT 256
#define MAXLINES 32
/* Reads at most maxLines inputs from stdin. Returns number of lines. */
int readlines(char** buffer, int maxLines, size_t maxInput);
/* Gets input from stdin with maxInput as the limit. Returns size of string. Terminates at newline. */
int getstdline(char* buffer, int maxInput);
int main(int argc, char** argv) {
char** buffer = malloc((sizeof buffer[0]) * MAXLINES);
int numlines = readlines(buffer, MAXLINES, MAXINPUT);
/* free memory that was allocated for each str */
for(int i = 0; i < numlines; ++i) {
free(*(buffer++));
}
/* free memory that was allocated to hold all the strings */
free(buffer);
}
int readlines(char** buffer, int maxLines, size_t maxInput) {
int linecount = 0;
while(maxLines--) {
char* tmp = malloc(maxInput);
/* if empty string, exit loop */
if(getstdline(tmp, maxInput) <= 0) {
free(tmp);
break;
}
*buffer = tmp;
++linecount;
++buffer;
}
return linecount;
}
My question is regarding the call to malloc() in readlines(char**,int,size_t). I obviously can't free() the memory within the function so to free it at the end of the program, I tried to loop through the array of char* and free them individually. I then also free char** buffer in main() because it was also allocated using malloc().
Looping through each of them gives me the error :
object was probably modified after being freed.
Freeing char** buffer at the end works fine.
So it seems there is a concept of dynamic memory I am not quite understanding. Why is this happening and what would be the correct way to handle memory in this specific program?
The problem is that you are modifying the buffer pointer by running buffer++ so when you call free(buffer) you are passing in the wrong pointer. You can rewrite your loop to not modify that pointer.

C: System calls and pointers to reverse a file

Solved. Thanks lutogniew.....just over complicating it...
So I am having some trouble with a homework assignment. The assignment is to take in a file (using only system calls), reverse it and write an output file with that reversed data on it (ASCII only). A catch is that the reverse section has to be done with pointers. I did the following below, which does work. However, it does not use pointers to reverse.
My question I guess, is how can I access something like data[] using pointers? Or, how can I read from the file into it. Everything I tried (mostly char**) only reads in null.
Any help would be much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int i = 0;
int fileOut = open("output.txt", O_WRONLY | O_APPEND);
int fileIn = open("input.txt", O_RDONLY);
int start = lseek(fileIn, 0 , SEEK_CUR);
int end = lseek(fileIn, 0 , SEEK_END);
int restart = lseek(fileIn, 0-end , SEEK_CUR);
char data[end];
char reverseData[end];
read(fileIn, data, end);
for(i = 0; i< end; i++){
reverseData[i] = data[end-(i+1)];
}
write(fileOut, reverseData, end);
return 0;
}
After Accept Answer.
Something for OP to consider as another approach:
For fun, a not-so-serious recursive approach to reverse the file.
void reverse(int fileIn, int fileOut) {
char data;
if (read(fileIn, &data, 1) == 1) {
reverse(fileIn, fileOut);
write(fileOut, &data, 1);
}
}
int main(void) {
int fileOut = open("output.txt", O_WRONLY | O_APPEND);
int fileIn = open("input.txt", O_RDONLY);
reverse(fileIn, fileOut);
close(fileIn);
close(fileOut);
return 0;
}
You must understand that what is presented to you as an array in C, in reality is just a pointer, pointing to the beginning of the memory belonging to that array. This snippet should make everything quite clear:
int test[] = { 1, 2, 3 };
int* ptr = test + 2; // ptr now points to the third element
EDIT
As for loading data into an array: again, remember that array itself is just a pool of memory (a buffer) - it begins where the pointer mentioned above points to, and has the size equal to numberOfElements * sizeOfSingleElement. Now look at the signature of the read function:
size_t read(int fildes, void* buf, size_t nbytes);
It reads nbytes into buffer pointed to by buf. Rings a bell?

Resources