My array is defined like this
int buffSize = 80;
char* buff = (char*) malloc(sizeof(char) * buffSize);
First, I thought &buff should be the same as &buff[0], but apparently, it isn't! Did I miss something here?
This statement prints two different values for those two:
printf("COMPARE: buff=%u, buff[0]=%u\n", &buff, &buff[0]);
Second, the reason I asked is because I'm trying to create a big buffer and "manually" divide it up to use with getline.
Basically, I'd like to do something like this:
int byte_read, total_read = 0;
do
{
read = getline(&buff[totalRead], buffSize, inFile); //where inFile is just a file handler
totalRead += read;
}
while (byte_read > 0);
buff is a pointer, and &buff is the address of that pointer. On the other hand, &buff[0] is the address of the location the pointer points to, and should have the same value as buff.
In summary, expect buff and &buff[0] to have the same value.
Related
My program has a variable number of args and I need to make an execv with a new path, so I want to change the value of argv[1] in a different variable without changing it, but it won't let me.
char** arg_exec = malloc(argc * sizeof (char*));
int i;
for(i=0;i <= argc-1; i++)
arg_exec[i] = strdup(argv[i]);
arg_exec[argc] = NULL;
if( (pid = fork()) == 0){
arg_exec[1] = strcat(directory , dir_info->d_name); //some variables with the current path and a name
execv(arg_exec[0], arg_exec);
printf("Error in process %d\n", getpid());
return 1;
}
but after it runs this line arg_exec[1] = strcat(directory , dir_info->d_name); it changes my value of argv[1], and my program fails..
It worked fine with execl, since it was like execl(argv[0],strcat(directory , dir_info->d_name), ..., NULL); but because I have a variable number of arguments to run it, it wouldn't be good to implement that way.
Edit1: Added NULL at the end of the array
Edit2: I'm doing a version of the find, so strcat will add to the current directory a folder to look into.
This is the initalization of the directory:
char *directory = strcat(argv[1],"/");
char *directory = strcat(argv[1],"/"); attemps to modify argv[1] beyond its allocation, which is UB. #alk.
Modifying argv itself may be UB. Is argv[n] writable?
So allocate memory for both.
Note: char** arg_exec = malloc(argc * sizeof (char*)); is insufficient as argv[argc] must be NULL. Need 1 more. Notice argc is not passed to execv().
Step 1. Make a copy of the pointer array argv[]
char **argv_new;
size_t a_size = sizeof *argv_new * (argc + 1); // + 1 for the final NULL
argv_new = malloc(a_size);
memcpy(argv_new, argv, a_size);
Step 2. Form the new arg[1]
int size = 1 + snprintf(NULL, 0, "%s/%s", argv[1], dir_info->d_name);
argv_new[1] = malloc(size);
snprintf(argv_new[1], size, "%s/%s", argv[1], dir_info->d_name);
Use it
execv(arg_new[0], arg_new);
free(argv_new[1]);
free(argv_new);
TBD: Error checking to add for: argc > 1, malloc(), snprintf(), execv()
You do not show how directory is set. I suspect that it's something like
char *directory = argv[1];
In that case, strcat will modify the location directory is pointing to and hence argv.
The code as shown misses to NULL-terminate the target pointer array arg_exec.
To do so allocate one more element then needed and explicitly set it to NULL.
Also the second assignment the code does to arg_exe's elements overwrites the result of the first, causing a memory leak, as the address to the memory allocate by strdup() is lost.
Assuming argv gets passed in via main(), then this line
char *directory = strcat(argv[1],"/");
tries to concatenate "/" to what argv[1] is pointing to and with this writes beyond the bounds of argv[1] and by doing so invokes undefined behaviour. From then on anything can happen, from crash to seeming to work.
BTW; please note that directory is just a pointer to char, so it does not provide any memory to store any "string"-like values.
What you probably want instead of
char *directory = strcat(argv[1],"/");
...
arg_exec[1] = strcat(directory , dir_info->d_name);
is something like this (this assumes argv[1] holds any "base"-directorie's name and argv_exe is allocated and initialised as per your (corrected) code):
{
void * tmp = realloc(arg_exec[1],
strlen(arg_exec[1]) + strlen("/") + strlen(dir_info->d_name) + 1);
if (NULL == tmp)
{
perror("realloc() failed");
exit(1);
}
arg_exec[1] = tmp;
}
strcat(arg_exec[1], "/");
strcat(arg_exec[1], dir_info->d_name);
Fairly simple question regarding malloc. What is the max that I can set within the allocated area. For instance:
char *buffer;
buffer = malloc(20);
buffer[19] = 'a'; //Is this the highest spot I can set?
buffer[20] = 'a'; //Or is this the highest spot I can set?
free(buffer);
The phrasing of your question is a bit off. You mean "what is the maximum index I can use for an allocated block of memory". The answer is the same as for arrays.
If you are reading or writing the memory, you may safely use indices between (and including) 0 and one less than the size of the block (in your case, that means index 19). All up, that means you can access the 20 values that you asked for.
If you are simply obtaining the pointer for comparison with other pointers inside the same block (and you are not going to read or write to it), you may additionally obtain the pointer one-past-the-end (in your case that means index 20).
To clarify these things with examples:
Yes, buffer[19] = 'a'; is the very last value you may access in a read or write capacity. Don't forget that if you want to store a string in this memory, and hand it to functions that expect a null-terminated string, this slot is your last chance to put that value of '\0'.
You are allowed to access buffer[20] in the following manner:
char *p;
for( p = &buffer[0]; p != &buffer[20]; ++p )
{
putc( *p, stdout );
}
This is useful because of the way we tend to iterate over memory and store sizes. It would make our code quite less readable if we had to subtract 1 all over the place.
Oh, and it gives you the neat trick:
size_t buf_size = 20;
char *buffer = malloc(buf_size);
char *start = buffer;
char *end = buffer + buf_size;
size_t oops_i_forgot_the_size = end - start;
malloc(x) will allocate x bytes.
So by accessing buffer[0] you access the first byte, by accessing buffer[1] you access the second.
e.g
char * buffer = (char *) malloc(1);
buffer[0] = 0; // legal
buffer[1] = 0; // illegal
I'm trying to read into a buffer passed as a pointer to this function. memcpy() works fine and the data is stored correctly in buffer, but when I access buffer outside of the function it is null. There's some pointer issue I'm not getting here.
Here's the code, I took out most of it, I know it copies the data correctly, but it doesn't pass it to the buffer pointer. Ideas?
int read(file file, char *buffer , int maxlen) {
int bytes_read;
// copy data to file buffer
bytes_read = min(maxlen, file->file_size - file->cursor);
buffer = (char*) malloc(bytes_read);
memcpy(buffer , file->buffer + file->cursor, bytes_read);
return bytes_read;
}
The problem is pretty simple: you are modifying the variable "buffer". Since it is passed by value and not by reference, the calling function doesn't see the change. In order to make the change to buffer visible, you need to pass in a pointer to buffer.
Your function would then look like this:
int read(file file, char **buffer , int maxlen) {
int bytes_read;
// copy data to file buffer
bytes_read = min(maxlen, file->file_size - file->cursor);
*buffer = (char*) malloc(bytes_read);
memcpy(*buffer , file->buffer + file->cursor, bytes_read);
return bytes_read;
}
to call the function:
rv = read(file, &buffer, maxlen);
You cannot modify buffer directly because C uses pass by value with parameters. Therefore it is a copy of the pointer you are modifying. To change the pointer you need to change your function prototype to take a char** and allocate to the first level of indirection on that.
As a crude example of this:
void read(char** buffer , int byte_size) {
*buffer = (char*) malloc(byte_size);
}
and use where required with something like
char* buffer;
read(&buffer,10); /* now buffer points to dynamically allocated array of 10 chars */
I receive a char * buffer which have the lenght of 10.
But I want to concat the whole content in my struct which have an variable char *.
typedef struct{
char *buffer;
//..
}file_entry;
file_entry real[128];
int fs_write(char *buffer, int size, int file) {
//every time this function is called buffer have 10 of lenght only
// I want to concat the whole text in my char* in my struct
}
Something like this :
real[i].buffer += buffer;
How can I do this in C ?
In general, do the following (adjust and add error checking as you see fit)
// real[i].buffer += buffer;
// Determine new size
int newSize = strlen(real[i].buffer) + strlen(buffer) + 1;
// Allocate new buffer
char * newBuffer = (char *)malloc(newSize);
// do the copy and concat
strcpy(newBuffer,real[i].buffer);
strcat(newBuffer,buffer); // or strncat
// release old buffer
free(real[i].buffer);
// store new pointer
real[i].buffer = newBuffer;
You can use strcat(3) to concatenate strings. Make sure you have allocated enough space at the destination!
Note that just calling strcat() a bunch of times will result in a Schlemiel the Painter's algorithm. Keeping track of the total length in your structure (or elsewhere, if you prefer) will help you out with that.
I am not clear. Do you want:
to concatenate every one of the 10 character buffers you receive into one array, pointed at by one real[0].buffer, or
do you want each 10 character buffer to be pointed at by a different real[i].buffer, or
something else?
You will need to allocate enough space for the copy of the buffer:
#include <stdlib.h>
//...
int size = 10+1; // need to allocate enough space for a terminating '\0'
char* buff = (char *)malloc(size);
if (buff == NULL) {
fprintf(stderr, "Error: Failed to allocate %d bytes in file: %s, line %d\n",
size, __FILE__, __LINE__ );
exit(1);
}
buff[0] = '\0'; // terminate the string so that strcat can work, if needed
//...
real[i].buffer = buff; // now buffer points at some space
//...
strncpy(real[i].buffer, buffer, size-1);
I'm new to C and am trying to use the read function. I want to take what's in the buffer (tempChar) and put it in another char array (str). This is so I can run the read function again and add on to str later (because tempChar will be rewritten by the 2nd read function). Like this:
char tempChar;
read(0, &tempChar, 10);
char *str;
str= (char*) malloc(10);
memcpy(str, &tempChar, fileSize); /*I'm doing something wrong here*/
All this so I can rerun:
read(0,&tempChar, 1);
str= realloc(str, 11);
str[10]=tempChar;
It compiles fine, but it gives me a segmentation fault when I actually try to run it.
Any ideas? Thanks a bunch.
you need to have enough storage to store the 10 characters you are reading
you declared
char tempChar
which can hold 1 character.
Instead declare tempChar as
char tempChar[10];
char tempChar;
read(0, &tempChar, 10);
You are reading 10 characters from the file into memory only the size of a single char.
char tempChar only reserves memory for a single character, &tempChar points to this single byte of memory.
char *str;
str= (char*) malloc(10);
// why not now do ?
read(0, str, 10);
char tempChar;
Only allocates 1 byte. So you can only hold there 1 char. When you memcpy() you request to copy 10 bytes, which do not exist. Hence you read memory you should not causing Undefined Behaviour (which gives you the SegFault).
You should do something like you did with malloc() for str or declare a local array like char chatTemp[10]. Note: malloc() does not require a cast in C.
If you want to read twice and put the results next to each other in the same buffer, you don't need a temporary buffer for that: you can use pointer arithmetic to tell read to use the second half of the original buffer. Like so:
char buf[10];
ssize_t nread = read(0, buf, 5);
if (nread < 0)
error();
else
{
nread = read(0, buf + nread, sizeof buf - nread);
if (nread < 0)
error();
}
You need to give a file descriptor as a first parameter to read function.. Also you need to allocate char * buffer instead of char tempChar;
Check sample usage