Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a C-Style array to std::array transition completely safe for arrays?

First time questioner :) Is it possible to transform global c-style arrays to std::arrays without breaking the code? I'm working on a project which consists of decompiling the source code of an old game. We have already managed to refactor a large part of the disassembly/decompilation output. Since it's automatic there are still sections like

  int a;
  int b[50];
  *(&a + 100) = xxx;

or

  int b[50];
  int a;
  *(&a - 100) = xxx;

and other types of crazy pointer arithmetics remaining, which have yet to be refactored manually. But we would like to use bounds checking for sections that have been (presumably) correctly changed to arrays.

(Ignore the text in italics, I'm keeping it just for consistency in the comments)I've found one problem so far with chaning every array: sizeof(class containing array) would change. This could break code in some cycles, for example someclass somearray[100]; //for example (sizeof(somearray[0]) == 50) is true int pointer = (int)somearray; pointer += 100 ((someclass)pointer)->doSomething(); .because pointer +=100 wouldn't be pointing to the second element, but somewhere inside the first, or even zeroth, I'm not sure (don't forget it's automatically decompiled code, hence the ugliness).

I'm thinking of changing every global array to std::array and every instance of accessing the array without the [] operator to array._Elems.

Are there any problems that might arise if I were to change global arrays to std::arrays in code such as this?

Edit You were right about the size not changing. I had an error in the testing functions. So I'll expand the question:

Is it safe to change every c-style array to std::array?

Edit Our current code is actually only runnable in debug mode, since it doesn't move variables around. Release mode crashes basically at the start of the program.

Edit Since there seems to be some confusion what this question is about, let me clarify: Is there some guarantee that there's no other member in the array, other than T elems [N] ? Can I count on having

array<array<int,10>, 10> varname;
int* ptr = &varname[0][0];
ptr += 10

and be sure that ptr is pointing at varname[1][0] regardless of implementation details? Although it's guaranteed that an array is contiguous, I'm not sure about this. The standard contains an implementation, but I'm not sure whether that's an example implementation or the actual definition which every implementation should adhere with iterator and const_iterator being the only things that are implementation specific, since only those have the words implementation-defined (I don't have the latest specifiation at hand, so there might be some other differences).

like image 764
Silvester Avatar asked Jun 06 '13 13:06

Silvester


1 Answers

For one-dimensional arrays, this might work in all cases, the 2D case is more tricky:

In principle, it is possible for the std::array < > template to only consist of the array itself because its length argument is a compile time variable which does not need to be stored. However, your STL-implementation might have chosen to store it anyway, or any other data it needs. So, while '&a[n] == &a[0] + n' holds for any std::array, the expression '&a[n][0] == &a[0][0] + n*arrayWidth' might not hold for a 'std::array < std::array, arrayHeight >'.

Still you might want to check whether 'sizeof(std::array < int, 100 >) == sizeof(int) * 100' with your STL-implementation. If it does, it should be safe to replace even the 2D arrays.

like image 105
cmaster - reinstate monica Avatar answered Oct 16 '22 10:10

cmaster - reinstate monica