apache / apache/arrow

"NumericArray" and its instantiations are not exported and causes issue on Android when `-fvisibility=hidden` is used

Open
#35,465 2 comments 0 reactions 0 assignees View on GitHub
Component: C++ Type: bug
Dominant language
C++
Stars
17.1k
Forks
4.3k
Avg merge
3d 13h
Merged PRs (30d)
88

Description

### Describe the bug, including details regarding any error messages, version, and platform.

Currently, the `ARROW_EXPORT` attribute is not added for class `NumericArray`, nor its instantiation classes, and it causes issue on Android when `-fvisibility=hidden` is used.

If an application is linked with `libarrow.so`, a `NumericArray` object created inside `libarrow.so` seems to be considered as a different type than `NumericArray` type used in the application. Therefore, operations like `dynamic_cast` or `dynamic_pointer_cast` will fail.

Here is a specific example:

```
#include

#include "arrow/array/array_primitive.h"
#include "arrow/array/util.h"

int main()
{
auto array = *MakeArrayOfNull(arrow::uint64(), 100);
auto uint64_array = std::dynamic_pointer_cast(array);
if (uint64_array)
{
printf("dynamic_cast is successful\n");
}
else
{
printf("dynamic_cast failed\n");
}
return 0;
}
```

Note that `MakeArrayOfNull(arrow::uint64(), 100)` causes arrow library to generate a `NumericArray` (aka `UInt64Array`) object, and coverts it to its base class pointer `Array`, then return it. Then the app tries to cast it back to `UInt64Array`, but on Android, the operation fails, i.e. the output is `dynamic_cast failed`.

This is only observed on Android. It doesn't happen on Linux. Initially I thought it's because of compiler difference, as Android uses Clang. But I then observed that even if I use Clang to build both arrow and the sample app on Linux, the issue won't reproduce. So it might be related to the dynamic linker implementation difference on Android and Linux.

I also noticed that if `ARROW_EXPORT` is added for `class NumericArray` declaration in `arrow/cpp/src/arrow/type_fwd.h` ([code](https://github.com/apache/arrow/blob/main/cpp/src/arrow/type_fwd.h#L188)), then the issue goes away. However, it doesn't work if we the export at class defination in `arrow/cpp/src/arrow/array/array_primitive.h` ([code](https://github.com/apache/arrow/blob/main/cpp/src/arrow/array/array_primitive.h#L87)), maybe because it's a template class and the declarations of instantiations like `UInt64Array` are in `arrow/cpp/src/arrow/type_fwd.h` ([code](https://github.com/apache/arrow/blob/main/cpp/src//arrow/type_fwd.h#L196-L215)).

### Component(s)

C++

Contributor guide

Open the contributing guide

Research direction

Start with the NumericArray declaration and instantiation declarations in cpp/src/arrow/type_fwd.h, then compare them with the template definition in cpp/src/arrow/array/array_primitive.h. Reproduce the dynamic_pointer_cast failure on Android with -fvisibility=hidden using the MakeArrayOfNull example. Done means the generated numeric array types can be cast back successfully from an application linked to libarrow.so.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, cpp
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.