Я написал пакет R, включающий код C++, и он доступен здесь: https://github.com/pachadotdev/open-red ... /main/rpkg
Этот пакет протестирован с широким спектром операционных систем, версий R и компиляторов (например, таких как Ubuntu 22.04 + R Stable 4.4.1 + GCC 14). Это дополняется всесторонним тестированием игрушечных (но реалистичных) данных здесь: https://github.com/pachadotdev/open-red ... 1744283184.
Проблема
В настоящее время пакет был удален из-за конкретной ошибки, которая проявляется только в CLANG-ASAN/UBSAN, которую мне удалось воспроизвести здесь: https://github.com/pachadotdev/open-red ... 2719024104.
Другие компиляторы (и параметры компилятора) не возвращают эту ошибку и код проходит все проверки, как и в случае с CLANG 20, CLANG 15 на M1, GCC 14, и т. д.
Проблема, видимо, не в моем коде, а в выпуске libc для Ubuntu, описанном на https://github.com/microsoft/DirectXSha ... ssues/5971).
Вопрос
Как мне подойти к этой проблеме? Что указало бы мне в правильном направлении?
Добавление расширенных тестов ГСГ было хорошим шагом вперед, я думаю.
Я знаю, что это очень длинный пост, мои извинения.
Сообщения об ошибках
Вот соответствующие результаты проверки CLAN-ASAN на GitHub Actions:==4221==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x506000009fe0
#0 0x562588615306 in free (/opt/R/devel-asan/lib/R/bin/exec/R+0xc6306) (BuildId: 178e357df79b1589a38c1949da5e5f022d4bb535)
#1 0x7f597889bb6b in std::invalid_argument::~invalid_argument() (/usr/lib/x86_64-linux-gnu/libc++abi.so.1+0x27b6b) (BuildId: 6c74e28f72d8f0d900c51852b881a0b4ecbdccd4)
#2 0x7f594be0afd2 in RedatamLib::GetFileExtension(std::__1::basic_string const&) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/redatamlib/utils.cpp:92:3
#3 0x7f594bdfe9cf in RedatamLib::RedatamDatabase::OpenDictionary(std::__1::basic_string const&) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/redatamlib/entities/RedatamDatabase.cpp:27:16
#4 0x7f594bdfe806 in RedatamLib::RedatamDatabase::RedatamDatabase(std::__1::basic_string const&) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/redatamlib/entities/RedatamDatabase.cpp:18:3
#5 0x7f594be0b5a8 in export_redatam_to_list_(std::__1::basic_string) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/main.cpp:13:33
#6 0x7f594be0c2e8 in _redatam_export_redatam_to_list_ /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/cpp11.cpp:12:27
#7 0x7f5978a9e700 in R_doDotCall /tmp/R-devel/src/main/dotcode.c:754:11
...
#47 0x7f5978b3127a in Rf_mainloop /tmp/R-devel/src/main/main.c
#48 0x562588654c07 in main /tmp/R-devel/src/main/Rmain.c:29:5
#49 0x7f5978549d8f (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
#50 0x7f5978549e3f in __libc_start_main (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
#51 0x56258857b364 in _start (/opt/R/devel-asan/lib/R/bin/exec/R+0x2c364) (BuildId: 178e357df79b1589a38c1949da5e5f022d4bb535)
0x506000009fe0 is located 0 bytes inside of 56-byte region [0x506000009fe0,0x50600000a018)
allocated by thread T0 here:
#0 0x5625886528fd in operator new(unsigned long) (/opt/R/devel-asan/lib/R/bin/exec/R+0x1038fd) (BuildId: 178e357df79b1589a38c1949da5e5f022d4bb535)
#1 0x7f597890143f in std::logic_error::logic_error(char const*) (/usr/lib/x86_64-linux-gnu/libc++.so.1+0x5243f) (BuildId: f9cf67a269c0636459976458f48bd8994dce16aa)
#2 0x7f594bdfe9cf in RedatamLib::RedatamDatabase::OpenDictionary(std::__1::basic_string const&) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/redatamlib/entities/RedatamDatabase.cpp:27:16
#3 0x7f594bdfe806 in RedatamLib::RedatamDatabase::RedatamDatabase(std::__1::basic_string const&) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/redatamlib/entities/RedatamDatabase.cpp:18:3
#4 0x7f594be0b5a8 in export_redatam_to_list_(std::__1::basic_string) /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/main.cpp:13:33
#5 0x7f594be0c2e8 in _redatam_export_redatam_to_list_ /tmp/RtmpImHtWL/filea695de59adf/redatam.Rcheck/00_pkg_src/redatam/src/cpp11.cpp:12:27
#6 0x7f5978a9e700 in R_doDotCall /tmp/R-devel/src/main/dotcode.c:754:11
SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (/opt/R/devel-asan/lib/R/bin/exec/R+0xc6306) (BuildId: 178e357df79b1589a38c1949da5e5f022d4bb535) in free
==4221==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
==4221==ABORTING
Попытки решения
- Использовать файл конфигурации вместо Makevars, который «работает на моем ноутбуке»
PKG_CONFIG_NAME="redatam"
# Check for pkg-config
pkg-config --version >/dev/null 2>&1
if [ $? -eq 0 ]; then
PKGCONFIG_CFLAGS=`pkg-config --cflags --silence-errors`
PKGCONFIG_LIBS=`pkg-config --libs`
fi
# Set default flags
PKG_CFLAGS="-Ivendor -Iredatamlib -Iredatamlib/entities -Iredatamlib/exporters -Iredatamlib/readers"
PKG_LIBS="-Lvendor -Lredatamlib"
# Use pkg-config if available
if [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then
echo "Found pkg-config cflags and libs!"
PKG_CFLAGS=${PKGCONFIG_CFLAGS}
PKG_LIBS=${PKGCONFIG_LIBS}
fi
# Uncomment CXXFLAGS in Makevars.in to debug
# CXXFLAGS="-O0 -g -stdlib=libc++"
LDFLAGS="-stdlib=libc++"
# Write to Makevars using sed to replace placeholders
sed -e "s|@cflags@|$PKG_CFLAGS|" \
-e "s|@libs@|$PKG_LIBS|" \
-e "s|@cxxflags@|$CXXFLAGS|" \
-e "s|@ldflags@|$LDFLAGS|" \
src/Makevars.in > src/Makevars
# Success
exit 0
- Определите Makevars.in
PKG_LIBS=@libs@
# CXXFLAGS=@cxxflags@
LDFLAGS=@ldflags@
# Explicitly list all source files
SOURCES = vendor/pugixml.cpp \
redatamlib/readers/BitArrayReader.cpp \
redatamlib/readers/ByteArrayReader.cpp \
redatamlib/entities/Entity.cpp \
redatamlib/readers/FuzzyEntityParser.cpp \
redatamlib/readers/FuzzyVariableParser.cpp \
redatamlib/exporters/ParentIDCalculator.cpp \
redatamlib/exporters/RListExporter.cpp \
redatamlib/entities/RedatamDatabase.cpp \
redatamlib/entities/Variable.cpp \
redatamlib/readers/XMLParser.cpp \
redatamlib/utils.cpp \
main.cpp \
cpp11.cpp
# Convert source files to object files
OBJECTS = $(SOURCES:.cpp=.o)
all: $(SHLIB)
$(SHLIB): $(OBJECTS)
clean: rm -f $(OBJECTS) $(SHLIB)
Соответствующие строки кода
Я пытался сделать свой код более разборчивым, простым и минимальным, одновременно пытаясь решить проблему, но безуспешно.
Вот соответствующие части кода
GetFileExtension: https://github.com/pachadotdev/open-redatam/blob/main/ rpkg/src/redatamlib/utils.cpp#L92
string GetFileExtension(const string &fileName) {
size_t extPos = fileName.find_last_of('.');
// HERE //
ThrowIfBad(
extPos != string::npos,
invalid_argument("Error: No file extension found."));
string ext = fileName.substr(extPos);
std::transform(ext.begin(), ext.end(), ext.begin(),
[](unsigned char c) { return std::tolower(c); });
return ext;
}
Шаблоны ThrowIfBad: https://github.com/pachadotdev/open-red ... 38template
void ThrowIfBad(bool is_good_, std::error_code err_, const string &e_msg_) {
if (!is_good_) {
throw E(err_, e_msg_);
}
}
template void ThrowIfBad(bool is_good_, int errno_) {
if (!is_good_) {
throw E(std::error_code(errno_, std::generic_category()),
string(std::strerror(errno_)));
}
}
template void ThrowIfBad(bool is_good_, const E &e_) {
if (!is_good_) {
throw e_;
}
}
RedatamDatabase: https://github.com/pachadotdev/open-red ... se.cpp#L18
RedatamDatabase::RedatamDatabase(const string &fileName) {
cpp11::message("Opening dictionary file...");
// HERE //
OpenDictionary(fileName);
}
Определение OpenDictionary: https://github.com/pachadotdev/open-red ... pp#L26-L39
void RedatamDatabase::OpenDictionary(const string &fileName) {
string ext = GetFileExtension(fileName);
if (".dic" == ext) {
FuzzyEntityParser parser(fileName);
m_entities = parser.ParseEntities();
} else if (".dicx" == ext) {
XMLParser parser;
m_entities = parser.ParseFile(fileName);
} else {
throw std::invalid_argument(
"Error: Dictionary file's extension must be .dic or .dicx .");
}
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... in-r-packa