Can't seem to figure this out.

string *array;
 
void addNodes(string names[])
{
	array = names;
	//how many elements in the array???
}

Recommended Answers

All 33 Replies

>Can't seem to figure this out.
You're not the only one. There isn't a portable way to get the size of a dynamically allocated array. You need to pass the size to your function:

void addNodes(string names[], size_t size)
commented: Right ~~SpS +3

[humor]
keep accessing array elements from 0 until the program segfaults, then back up one and that's your limit.
[/humor]

commented: lol xD +5

I guess this would be helpful,
/******for a static array********/
char inp[4];
for (n=0;inp[n];n++)
; //do nothing inside the loop
cout<<n; //n will display the number of elements in the array inp[]

/******for dynamic array********/
char *arr = new char [sizeof(char)];
for (n=0;arr[n];n++)
; //do nothing inside the loop
cout<<n; //n will display the number of elements in the array arr[]

commented: BAD CODE +0
commented: "I guess this would be helpful" You guessed wrong.. +0

>> I guess this would be helpful
No, not a bit. Your code is wrong.

>> for (n=0;inp[n];n++)
Assuming that n was defined somewhere, the test for imp[n] against 0 is dngerous because imp is uninitialized. There could be a null character straight away, or 5000 characters later. You're really risking an access violation with this loop.

>> char *arr = new char [sizeof(char)];
This alloctes memory for one char. sizeof(char) is guaranteed to return 1, everywhere, without fail. That's one of the few absolutes when it comes to type sizes in C++.

>> for (n=0;arr[n];n++)
You have the same problem here as the previous loop.

Yes, your idea is valid assuming there's some sentinel value at the end of the array to stop the loop on. With the original question that's difficult because any string object is valid in the general case. That's probably why you took it upon yourself to change the example to char so that you could use a null character as the sentinel.

The best solution is to avoid using arrays in the first place because they're unsafe and most people don't understand them well enough to avoid the pitfalls, as displayed by your flawed example. The std::vector class provides a good container that grows dynamically.

commented: Right ~~SpS +3

The easiest way to get the length of a dynamic array is this

sizeof(array)/sizeof(arraytype)

where array is your dynamic array and arraytype is the data type (for instance int)

Hope this helps :)

commented: Nope -1

>> The easiest way to get the length of a dynamic array is this
Is it? Forget about the 'array' part and look closely at the 'dynamic' part. A dynamic array is not an array, it's a pointer to a block of memory that can be subscripted like an array:

#include <iostream>

#define length(x) (sizeof(x) / sizeof(*(x)))

void foo(int a[])
{
  std::cout << "From foo(): " << length(a) << '\n';
}

int main()
{
  int *a = new int[10];
  int b[10];

  std::cout << "From main(): " << length(a) << '\n';
  foo(b);
}

So the sizeof trick just breaks silently when you use it on a dynamic array, or an array passed as a function parameter. Templates are a better solution because they complain when you pass a pointer and not an array:

#include <iostream>

template <typename T, int sz>
char (&array(T(&)[sz]))[sz];

void foo(int a[])
{
  std::cout << "From foo(): " << sizeof array(a) << '\n';
}

int main()
{
  int *a = new int[10];
  int b[10];

  std::cout << "From main(): " << sizeof array(a) << '\n';
  foo(b);
}

The rule of thumb is that if you want the size of a dynamic array, you save it! If you want the size of an array parameter, you pass it! Anyone who doesn't know these rules or isn't comfortable with them would be better off using a smart container like std::vector or boost::array.

Ok so i mistyped. Just make it this and it will work (i think)
sizeof(*names)/sizeof(string)

Happy?

P.S. btw i know to pass the length of a dynamic array or to use vector but im just trying to solve this guy's problem. (so stop criticizing people)

Try it with a dynamic array and find out you are wrong.

You are being helpfully corrected, you are the one starting to get out of line.

I get 4 for the sizeof(string), hmmm?
I 'd say vectorize!

>> Just make it this and it will work (i think)
No offense, but when you're guessing, you're not helping. Most of the time a guess is either grievously wrong, or has subtle problems.

>> so stop criticizing people
It's called constructive criticism. If you don't want to learn then don't bother trying to help because you'll just give bad advice. If you think you know everything then don't bother trying to help because you'll probably give bad advice and then turn the thread into a flame war when someone who knows better corrects you.

I tried using the sizeof operator as suggested above. But everytime for an int array it gives "1" as output and for a char array it gives "4". No matter how many elements I store in the array.
I donot know the usage of std::vector or boost::array. Can someone help? Pls tell me how can I get the number of elements stored in a dynamic array using them?

P.S:I had changed the example to char type as I was not sure if 'String' is a valid data type in C or C++. Is it?

Basically, the only way to do this is what narue suggested and pass in the actual size as a parameter to the function. Either that, or use an STL collection, and use .size()

commented: Correct ~~SpS +3

>> I tried using the sizeof operator as suggested above.
Don't bother, it won't work.

>> Pls tell me how can I get the number of elements stored in a dynamic array using them?
The only way to get the size of a dynamic array is to save the size when you allocate memory. The only way to get the size of an array parameter is to pass the size as another parameter:

// Get the size of a dynamic array
char *p = new char[10];
int sz = 10; // Save the size!
// Get the size of an array parameter
void foo(char array[], int size); // Pass the size!

>> I donot know the usage of std::vector or boost::array.
That's not a good excuse. ;) If you don't know the usage of a feature but you clearly need it, then it's time to learn. It's almost always better to use a container class than it is to use arrays anyway. Arrays are error prone while container classes work hard to protect you from those potential errors.

>> Is it?
String is not, unless you define it yourself, std::string is a class in the standard library.

hi,

i'm studing computer sciences and i just met this problem.
i know it's been a long time the thread has been opened but i have one more question about it.

i already thought of passing the size of the dynamic array in parameter and i'm sure this will work fine, but as i am a studient, i always want to know more about it and even more when something seems wiered to me : if the only way of knowing the size of a dynamic array is by sending its size, how does free works ? you just pass the pointer as parameter and it cleans up the memory... i bet this function has the solution we are looking for.. but unfortunatly i have no books detailed enough to answer my question and i can't find anything on the web neither...

maybe there is a "Mister know-it-all" over here who can help me to understand that.

(i'm sorry if my english isn't verry correct but this is not my first language ;) and so, please don't make answers to hard to understand, thank you :D)

Can't seem to figure this out.

string *array;
 
void addNodes(string names[])
{
	array = names;
	//how many elements in the array???
}

std::string has a function size() that will tell the current size.

void addNodes(string names[])
{
	cout << "size of array is " << names.size() << "\n";
}

>> array = names;
That does not work because you variable names is a c++ class, not a pointer. If you want the pointer, then use c_str()

const char* array = names.c_str();

std::string has a function size() that will tell the current size.

void addNodes(string names[])
{
    cout << "size of array is " << names.size() << "\n";
}

Hmm...you are forgetting that names is an array of strings and not a std::string or a vector. So you can't apply the size( ) function to it, it is applicable to C++ containers, not array of containers. The only way to do this thing correctly is to do it like specified by Miss Narue in the second post.

Hmm...you are forgetting that names is an array of strings and not a std::string or a vector. So you can't apply the size( ) function to it, it is applicable to C++ containers, not array of containers. The only way to do this thing correctly is to do it like specified by Miss Narue in the second post.

Yes you are correct -- my mistake. Best thing for the op to do is use a vector instead of an array. I was wondering at the time how Narue could possibly make such a mistake -- turns out she didn't.

I'm not an expert, but I was reading this article:
http://www.icce.rug.nl/docs/cplusplus/cplusplus09.html#l153

Apparently, if you overloaded the operator delete like this:
void operator delete[](void *p, size_t size);

the parameter "size" will tell you how long the array is.

However, if you want the normal delete[], you'll have to write "::delete[]"

I'm not an expert, but I was reading this article:
http://www.icce.rug.nl/docs/cplusplus/cplusplus09.html#l153

Apparently, if you overloaded the operator delete like this:
void operator delete[](void *p, size_t size);

the parameter "size" will tell you how long the array is.

However, if you want the normal delete[], you'll have to write "::delete[]"

Curiously, the C++ standard does not actually specify what value is passed as the size_t argument. In practice, it would be reasonable to expect (hope?) it would have the value passed to the corresponding invocation of operator new[](). If so, it would have to be divided by sizeof(the_type) to get the number of elements.

Since the destructors of all elements of the array will have been invoked before operator delete[]() is actually called, there is not much that can be done with the size_t argument other than pass it to a deallocation function (eg ::operator delete[]()) or print out the number of elements that were in the array being deallocated. The elements themselves will no longer exist, so no operation on them is allowed.

Don't kill me for this (I know this must be the worst idea ever), but WOOH! I figured it out! :D

#include <iostream>
using namespace std;

void addNodes(string names[])
{
   bool exception = false;
   size_t length = 0;
   string temp;
   do {
      try {
         temp = names[length];
         ++length;
      } catch (...) {
         exception = true;
      }
   } while (!exception);

   // No idea why, but you have to take away 3
   cout << (length - 3);
}

int main() {
   string names[10];

   addNodes(names);

   cin.ignore();
   return 0;
}

edit: but I just realised this doesn't even work if you dynamically allocate the names.. darn

I don't understand why this ancient thread is vivified.

It's impossible to get an array size by array parameter only.
For slow-witted reanimators: it's impossible in C and C++ to get a size of array argument by this array parameter only.

You all reanimators forget that:
1. An array parameter is a pointer to the 1st array element only; it's not a pointer to some kind of array descriptor. For example, you may pass a pointer to subarray of an arbitrary array - it's a valid argument for an array parameter.
2. It's impossible to recognize in a portable and standard conforming manner what's a storage class of a passed array argument - is it static, automatic or dynamic (heap allocated). So all tricks with delete operator overloading are senseless: you can't delete static or automatic arrays (you can try to do it, of course, but you know what happens after that).
3. Obviously, williamhemsworth's trick does not work too:
3.1 Illegal outside array boundaries access is capable to get (senseless) result without exception.
3.2 The C++ Language Standard does not require that memory access violation translated to C++ exception.

Regrettably, starting question of this thread was incorrect and inexact (3 years ago, today and tomorrow). It was a mix of two distinct issues: how builtin operator delete [] recognizes deleted array size and how to get array argument size by array parameter. The answer to the 2nd part - see this post. The answer to the 1st part: the C++ language Standard does not specify operator delete[] implementation; in practice most of C++ implementations allocate special memory descriptor just BEFORE allocated array memory chunk...

Please, don't waste time and traffic on idle discussions...

Since the destructors of all elements of the array will have been invoked before operator elete[]() is actually called, there is not much that can be done with the size_t argument other than pass it to a deallocation function (eg ::operator delete[]()) or print out the number of elements that were in the array being deallocated. The elements themselves will no longer exist, so no operation on them is allowed.

I agree about the destructors being called, but I tried monitoring the memory status on my computer whilst stepping through the following code, and the memory doesn't seem to get freed untill you explicitly call the global delete[].

#include "stdafx.h"
#include <iostream>
using namespace std;
class obj{
public:
	obj(){}
	~obj(){}
	unsigned long long data[10000];
	void operator delete[] (void* ptr,size_t size){
		cout<<"in operator delete : ";
	}
};
int main(){
	obj* objs=new obj[1000];
	delete[] objs;
	delete[] objs;
	::delete[] objs;
	cout<<"everything gone!";
	return 0;
}

>the memory doesn't seem to get freed until you explicitly call the global delete[].
That's pretty obvious when you consider that your example is a glorified version of this:

#include <iostream>

using namespace std;

class obj {
public:
  void do_delete()
  {
    cout<<"In do_delete\n";
  }
};

int main()
{
  obj *p = new obj[1000];

  p->do_delete();
  p->do_delete();

  delete[] p;

  cout<<"Everything gone!\n";
}

You managed to hide the inanity of your example by using operator overloading. Your overloaded delete doesn't do jack except print a message. The actual memory is allocated and owned by the global operator new, which can then logically only be released by the global operator delete.

As Narue said, the reason is that your class's operator delete() does not release the memory. If you do this;

void operator delete[] (void* ptr,size_t size){
		cout<<"in operator delete : ";
                ::operator delete[](ptr);
	}

it will release the memory.

The whole purpose of overloading an operator delete is to correctly manage deallocation. In other words, you have to do it.

> For slow-witted reanimators: it's impossible in C and C++ to get a size of array argument by this array parameter only.

Funny how there are all kinds of C and C++ libraries to do just that sort of thing. They are most popular for debugging and finding memory leaks. A very good library is DUMA. There are others.

The thing they typically have in common is judicious allocation of memory such that any invalid access will generate a page fault --which can be intercepted and interrogated.

WW's trick likely fails for two reasons, though neither are "obvious":

3.2 C++ exceptions != OS exceptions --but it is a common Win32 compiler option to integrate SEH into C++'s exception handling (and it can be done on other platforms too)

3.1 ...because you may very well own the memory outside of the array's bounds. This can happen 1) because the mm can divy its pool (called "the heap") any way it likes, and 2) because your object is very likely data-aligned. In WW's case, it appears to be on 32-bit boundries.


> Regrettably, starting question of this thread was incorrect and inexact...

Fortunate how forums like this exist to clarify such confusions, no?


> Please, don't waste time and traffic on idle discussions...

Please, don't waste bandwith on content-free, self-aggrandizing high-mindedness. If the topic was worth closing it would have been two years ago. Or perhaps people like Narue and AD are too dimwitted to judge stupid topics.

"

As Narue said, the reason is that your class's operator delete() does not release the memory.

"

"

>the memory doesn't seem to get freed until you explicitly call the global delete[].
That's pretty obvious when you consider that your example is a glorified version of this:

"

I don't think you've understood the point that I'm trying to make (partly my fault: I should have reiterated what I said in my first post). I wasn't complaining that my delete[] doesn't delete - it's not supposed to delete! I'm trying to say that by overloading the delete[] operator with both the void* and the size_t parameter, you CAN find the size of a dynamic array from just the pointer. Although the destructor will be called, the memory will not be freed until, as I said, "you explicitly call the global delete[]". This means that as long as you declare an empty destructor, finding the length in bytes of the array will not affect the array in any way shape or form.

Yes, I know it's probably pointless to go to all that trouble when you could just store the array length, but I'm just saying that it is possible to find the size of a dynamic array.

>I'm trying to say that by overloading the delete[] operator[...]
Yea, your post didn't read like that at all.

>I'm just saying that it is possible to find the size of a dynamic array.
Not really. You're finding the size of a non-dynamic array within a dynamic object. That's far from the same thing, and you could easily do it without all of the rigmarole simply by taking the sizeof your object[1]:

#include <iostream>

class obj { unsigned char data[10000]; };

int main(){
  obj *objs = new obj[1000];

  std::cout<< sizeof *objs <<'\n';

  delete[] objs;
}

This is a variation of the age-old workaround for arrays being passed around by pointer rather than by value or reference (though it started in C and used structures rather than classes). There's no magic, and you're certainly not finding the length of a dynamic array, or more generally, determining the number of elements in an array given nothing but a pointer to the "first" element.

[1]: This is assuming that the class has no hidden data (such as a virtual table) and the only data member is the array.

int string::getsize()
{
	int n_itr=strlen(this->arr);
	n_itr*=sizeof(char);
	return n_itr;
}

Here string is my own class, it has only one data member that is ch* arr;.
and the getsize() returns the size of dynamic character array allocated through arr
in bytes.

hope this helps

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.