Hasnain
Hasnain

Reputation: 43

Segmentation fault when try to copy float vector of large size through memcpy

I am trying to copy a float vector into a void* variable through memcpy. If vector size is less than 3000, then below code works fine. But when try to copy vector of size greater than 3000, i got segmentation fault.

  void* process(std::string datatype) {
  //  given datatype will decide the dataype of vec.
  const uint64_t VEC_COUNT = 10; // vector size
  const uint64_t VEC_SZ = VEC_COUNT * sizeof(float);
  std::vector<float> float_vec;
  float_vec.reserve(VEC_COUNT);
  for (unsigned int i = 0; i < VEC_COUNT; ++i) {
    float val = (float)(rand() % 100) / 3.0f;
    float_vec.push_back(val);
  }

  void* data = nullptr;
  data = malloc(VEC_SZ);
  if (data == nullptr) {
    throw std::invalid_argument("Could not allocate memory for data!");
  }
  memcpy(data, &float_vec, VEC_SZ);
  }
 return data;
}

int main() {
 VEC_COUNT = 10; //will be same as in upper method
 void* data = process("float");
 std::vector<float> &k =
    *(static_cast<std::vector<float>*>(data));
  for (unsigned int i = 0; i < VEC_COUNT; ++i) {
    std::cout << "k[i] = " << k[i] << " , float_vec[i] = "
      << k[i] << std::endl;
}

Before memcpy, I am using malloc to allocate memory. malloc is not giving any type of segmentation fault but memcpy not working fine. When I run this code with gdb and backtrace segmentation fault, I got following error

__memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:249

Any help would be appreciated. Thanks

Upvotes: 1

Views: 1729

Answers (3)

eerorika
eerorika

Reputation: 238401

Vectors are not trivially copyable. Using memcpy on them has unspecified behaviour which may be undefined. Don't do this. Also, there is no need to use malloc in C++.

To copy a vector, this is an efficient solution:

std::vector<float> k = float_vec;

I have method which can return vector of any type and i don't want to use templates.

Return std::any.

Upvotes: 0

Stephan Lechner
Stephan Lechner

Reputation: 35154

A vector is just an "envelope" object holding a pointer to dynamically allocated memory that actually stores the elements. So if you take the address of the vector object itself, you are taking the address of the "envelope", but not that of the first element stored. So you are very likely reading beyound the bounds of the "envelop", and this is undefined behaviour; So it could be that it crashes with a size of 100, it could be that it does not crash with a size of 10000, but doing something else. At least it will not copy the actual elements as intended.

To get access to the memory where the vector actually stores the elements, use its member function data(). So the following command should do the job:

memcpy(data, float_vec.data(), VEC_SZ);

Upvotes: 2

Daniel Langr
Daniel Langr

Reputation: 23517

memcpy(data, &float_vec, VEC_SZ);

This cannot work, memcpy may be used only with trivially-copyable types, which std::vector is not.

What you likely want instead is:

memcpy(data, float_vec.data(), VEC_SZ);

Moreover, this:

std::vector<float> &k =
   *(static_cast<std::vector<float>*>(data));

is completely illegal. There is no object of type std::vector<float> on an address pointed to by data.

Upvotes: 3

Related Questions