LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-20-2012, 09:02 PM   #1
ejspeiro
Member
 
Registered: Feb 2011
Distribution: Ubuntu 14.04 LTS (Trusty Tahr)
Posts: 203

Rep: Reputation: 26
Question Is there anything analog to what would recalloc be?


Hi there guys,

I was writing some code for my research work, and I noticed that every time I reallocate my memory, i.e. every time I invoke remalloc, it actually does it work, but the reallocated array is not initialized.

I goggled for something as recalloc, but I do not see it out there.

Would it make sense for me to try to create it? Is there anything like it already out there?

Thanks in advanced!

\m/
 
Old 09-21-2012, 08:53 AM   #2
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
From the manual page for malloc():
Quote:
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized.

The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes.
If you want to clear the memory, use the memset() function:
Code:
(void) memset ((void *) ptr, '\0', sizeof (ptr));
Where ptr is the pointer to allocated memory and '\0' (null) is set in every position (you can set whatever you'd like).

See the manual page for malloc and for memset.

Hope this helps some.

Last edited by tronayne; 09-21-2012 at 08:56 AM.
 
Old 09-21-2012, 10:23 AM   #3
ejspeiro
Member
 
Registered: Feb 2011
Distribution: Ubuntu 14.04 LTS (Trusty Tahr)
Posts: 203

Original Poster
Rep: Reputation: 26
tronayne: Thanks for your reply, which makes sense.

Nonetheless, my original concerns stands: If you had already filled your array with say, 16 elements, and you are interested in reallocating it with extra 16 elements... would it make sense to use realloc and then memset? I do NOT think so, because memset would initialize the previously assigned values, wouldn't it? Unless, memset is somehow instructed to initialize only the "new" space.

Is there a way of doing that, considering the arguments memset takes?

Thanks.
 
Old 09-21-2012, 10:41 AM   #4
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
The stated purpose of realloc() would be defeated by setting the reallocated area to binary zeros.

There is a very-efficient library subroutine which will set an arbitrarily-large block of memory to known-zero. (This is actually how "calloc()" does it.) It may actually use a system call which invalidates the page-table entries for the specified area so that they become flagged as zero-pages without paging them in as a "memset()" type of call might do. Paged-out pages remain paged-out, but when and if demand-paged back in, they will be all-zeros.

Last edited by sundialsvcs; 09-21-2012 at 10:42 AM.
 
Old 09-21-2012, 10:43 AM   #5
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Quote:
Originally Posted by ejspeiro View Post
Is there a way of doing that, considering the arguments memset takes?
Sure. memset() takes a pointer to where you want to start, an initialize character (like '\0', NULL) and a length. You can do a little quick arithmetic, even fancy-schmancy arithmetic that's dynamic to figure out where to point and how far to go.

So, if you've got an area of memory that's 16 bytes long, and you know the beginning address, and you realloc() to add 16 bytes... eh?

Hope this helps some.
 
Old 09-21-2012, 10:44 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by tronayne View Post
If you want to clear the memory, use the memset() function:
Code:
(void) memset ((void *) ptr, '\0', sizeof (ptr));
You probably don't want to use sizeof(ptr) there.

Quote:
Originally Posted by ejspeiro
If you had already filled your array with say, 16 elements, and you are interested in reallocating it with extra 16 elements... would it make sense to use realloc and then memset? I do NOT think so, because memset would initialize the previously assigned values, wouldn't it? Unless, memset is somehow instructed to initialize only the "new" space.

Is there a way of doing that, considering the arguments memset takes?
Code:
memset(ptr + old_len, 0, sizeof(*ptr) * (new_len - old_len));
 
Old 09-21-2012, 10:45 AM   #7
ejspeiro
Member
 
Registered: Feb 2011
Distribution: Ubuntu 14.04 LTS (Trusty Tahr)
Posts: 203

Original Poster
Rep: Reputation: 26
sundialsvcs:

Quote:
The stated purpose of realloc() would be defeated by setting the reallocated area to binary zeroes.
Why?

tronayne: Wow! Cool! Yes... I suddenly thought on doing that... I does help a lot; thanks!

\m/ \m/
 
Old 09-21-2012, 10:48 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Code:
size_t requested;
size_t allocated;
char *ptr;

ptr= realloc (ptr, requested);
if (allocated<requested) memset (ptr+allocated, 0, requested-allocated);
allocated= requested;
 
1 members found this post helpful.
Old 09-21-2012, 11:02 AM   #9
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Quote:
Originally Posted by ntubski View Post
You probably don't want to use sizeof(ptr) there.
Oops (or, duh!); ought to be sizeof(*ptr).

Fumble finger.
 
Old 09-21-2012, 08:33 PM   #10
ejspeiro
Member
 
Registered: Feb 2011
Distribution: Ubuntu 14.04 LTS (Trusty Tahr)
Posts: 203

Original Poster
Rep: Reputation: 26
Hi guys... well this is the implementation that I have tried:

Code:
double *array;
int amount_of_elements;
int max_amount_of_elements;
int requested_memory;
int allocated_memory;
int ii;

array = NULL;
amount_of_elements = 4;
max_amount_of_elements = 16;
allocated_memory = 0;

while (amount_of_elements < max_amount_of_elements) {

  requested_memory = amount_of_elements*sizeof(double);

  // Reallocate the array AND initialize the new attained memory if the allocation is successful:
  array = (double*) realloc(array, requested_memory);
  if ((array != NULL) && (requested_memory > allocated_memory)) {
    memset(array + allocated_memory, 0, requested_memory - allocated_memory);
  } else {
    printf("Error.\n");
  }

  // If the reallocation worked, then update the amount of allocated memory:
  allocated_memory = requested_memory;

  // Print the array to make sure that the new memory interval has been indeed initialized:
  for (ii = 0; ii < amount_of_elements; ii++) {
    printf("%.3g ", array[ii]);
  }
  putchar('\n');

  // Fill the array to make sure that the new memory interval can be used:
  for (ii = 0; ii < amount_of_elements; ii++) {
    array[ii] = ii;
  }

  // Print the fill the array to make sure that the new memory interval can be used:
  for (ii = 0; ii < amount_of_elements; ii++) {
    printf("%.3g ", array[ii]);
  }
  putchar('\n');

  // Try with more elements:
  amount_of_elements = amount_of_elements + amount_of_elements;
}

free(array);
What am I doing wrong in terms of resetting? Because, this is the output that I get:

Code:
0 0 0 0 
0 1 2 3 
0 1 2 3 nan 2.37e-320 1.09e-312 1.09e-312 
0 1 2 3 4 5 6 7
As you can see... the first time, I realloc and successfully initialize, but for the second time... I have problem with the initialization to 0s, as it can be noticed by the presence of 'nan' and weird non-zero numbers as 2.37e-320.

Any hints?

I tried to use the bzero function, but since it is kind of an analog to memset, in the sense that you still have to specify the correct limits, I have the same issue.

Thanks!
 
Old 09-21-2012, 09:59 PM   #11
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Hi.

Quote:
Any hints?
Yes. Read carefully the description of memset() and realloc() functions in man pages:
Quote:
void *memset(void *s, int c, size_t n);
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
Quote:
void *realloc(void *ptr, size_t size);
The realloc() function changes the size of the memory block pointed to by ptr to size bytes.
You see what I mean? Sizes are in bytes. Only char variable occupies 1 byte of memory. Each double variable occupies few bytes. So, when you need a place in memory for, say N doubles, you should specify N*sizeof(double) (bytes).
 
Old 09-21-2012, 10:32 PM   #12
ejspeiro
Member
 
Registered: Feb 2011
Distribution: Ubuntu 14.04 LTS (Trusty Tahr)
Posts: 203

Original Poster
Rep: Reputation: 26
Hi firstfire,

thanks for your reply. But I really believe that the size of a double, i.e., 8 B, is already being considered, given the definition of requested_memory:

Code:
requested_memory = amount_of_elements*sizeof(double);
// Reallocate the array AND initialize the new attained memory if the allocation is successful:
array = (double*) realloc(array, requested_memory);
Furthermore, when I state the amount of data in memset... am I failing on doing it? Because, and please correct me if I am wrong, both values should have the info on the size of the data type within their definitions:

Code:
requested_memory - allocated_memory = amount_of_elements_iteration_ii*sizeof(double) - amount_of_elements_iteration_(ii-1)*sizeof(double) = [amount_of_elements_iteration_ii - amount_of_elements_iteration_(ii-1)]*sizeof(double)
Is this making nay sense?

Thanks!
 
Old 09-21-2012, 11:49 PM   #13
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Hi.

The problem is here
Code:
memset(array + allocated_memory, 0, requested_memory - allocated_memory);
When you write array+allocated_memory, because array is (double*), that is equivalent to &array[allocated_memory], which is definitely not what you wanted (so, array is too smart, it knows, that it consists of doubles). To overcome this difficulty you may write
Code:
memset((void*)array + allocated_memory, 0, (requested_memory - allocated_memory));

Last edited by firstfire; 09-21-2012 at 11:50 PM.
 
1 members found this post helpful.
Old 09-24-2012, 01:36 PM   #14
ejspeiro
Member
 
Registered: Feb 2011
Distribution: Ubuntu 14.04 LTS (Trusty Tahr)
Posts: 203

Original Poster
Rep: Reputation: 26
Talking

firstfire: Thanks! That completely solved the problem... and it makes perfect sense... I guess I don't quite understand (void*) well enough!

I am calling this one solved... here is the complete code that works:

Code:
      double *array;
      int amount_of_elements;
      int max_amount_of_elements;
      int requested_memory;
      int allocated_memory;
      int ii;

      array = NULL;
      amount_of_elements = 4;
      max_amount_of_elements = 16;
      allocated_memory = 0;
      while (amount_of_elements < max_amount_of_elements) {
        requested_memory = amount_of_elements*sizeof(double);
        array = (double*) realloc(array, requested_memory);
        if ((array != NULL) && (requested_memory > allocated_memory)) {
          memset( (void *)array + allocated_memory, 0, requested_memory - allocated_memory);
        } else {
          printf("Error.\n");
        }
        allocated_memory = requested_memory;
        for (ii = 0; ii < amount_of_elements; ii++) {
          printf("%.3g ", array[ii]);
        }
        putchar('\n');
        for (ii = 0; ii < amount_of_elements; ii++) {
          array[ii] = ii;
        }
        for (ii = 0; ii < amount_of_elements; ii++) {
          printf("%.3g ", array[ii]);
        }
        putchar('\n');
        amount_of_elements = amount_of_elements + amount_of_elements;
      }
      free(array);
Yielding the following output:

Code:
0 0 0 0 
0 1 2 3 
0 1 2 3 0 0 0 0 
0 1 2 3 4 5 6 7
From here, one could wrap the whole thing up to a recalloc function

Thanks everybody.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Analog Computers theKbStockpiler General 23 08-20-2012 07:41 PM
IEC958 in - to - Analog out (xbox360) apinta10 Linux - Hardware 1 06-06-2011 07:59 AM
Sidewinder and Analog Gamepads - Together BeauMN Linux - Hardware 1 12-02-2006 01:04 PM
Analog ePSXe? GT_Onizuka Linux - Games 6 10-24-2003 07:38 PM
analog recording luap Linux - Software 2 03-10-2003 12:25 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:57 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration