2015-10-20 20 views
5

Tôi đang nhận được một phân đoạn lạ khi sử dụng libxml để phân tích cú pháp tệp. Mã này đã làm việc trước đây khi tôi biên dịch nó dưới dạng ứng dụng 32 bit. Tôi đã thay đổi nó thành một ứng dụng 64 bit và nó ngừng hoạt động.Lỗi ngoài giới hạn khi đọc xml

Các lỗi seg đến trong lúc "if (xmlStrcmp (cur-> tên, (const xmlChar *) "máy chủ"))"

cur-> tên là một xmlChar const * và nó trỏ đến một địa chỉ mà nói ra giới hạn của nó. Nhưng khi tôi gỡ lỗi và đi đến vị trí bộ nhớ đó, dữ liệu đó là chính xác.

int XmlGetServers() 
{ 
xmlDocPtr doc; 
xmlNodePtr cur; 

doc = xmlParseFile("Pin.xml"); 
if (doc == NULL) 
{ 
    std::cout << "\n Pin.xml not parsed successfully." << std::endl; 
    return -1; 
} 
cur = xmlDocGetRootElement(doc); 

if (cur == NULL) 
{ 
    std::cout << "\n Pin.xml is empty document." << std::endl; 
    xmlFreeDoc(doc); 
    return -1; 
} 
if (xmlStrcmp(cur->name, (const xmlChar *) "servers")) 
{ 
    std::cout << "\n ERROR: Pin.xml of the wrong type, root node != servers." << std::endl; 
    xmlFreeDoc(doc); 
    return -1; 
} 
} 

Trước cur được khởi tạo tham số tên là

Name : name 
    Details:0xed11f72000007fff <Address 0xed11f72000007fff out of bounds> 

Sau cur được khởi tạo tham số tên được

Name : name 
    Details:0x64c43000000000 <Address 0x64c43000000000 out of bounds> 

Được tham chiếu XML tập tin

<?xml version="1.0"?> 

<servers> 

<server_info> 

    <server_name>Server1</server_name> 

    <server_ip>127.0.0.1</server_ip> 

    <server_data_port>9000</server_data_port> 

</server_info> 

<server_info> 

    <server_name>Server2</server_name> 

    <server_ip>127.0.0.1</server_ip> 

    <server_data_port>9001</server_data_port> 

</server_info> 

</servers> 

hệ thống:

OS: Redhat Enterprise Linux 6.4 64-bit

GCC: 4.4.7-3

gói: libxml2-2.7.6-8.el6_3.4.x86_64

+0

Bạn có phiên bản 64 bit của libxml không? – vmg

+0

yes libxml2-2.7.6-8.el6_3.4.x86_64 – user758114

+0

Bạn đã thử chạy ứng dụng bằng valgrind, như Sam Varshavchik đã làm chưa? –

Trả lời

0

Vấn đề là chúng tôi đã sử dụng gói #pragma (1) trong mã của chúng tôi, có nghĩa là các bool trong DOMParser được đóng gói xuống 1 byte, trong khi Xerces không #pragma đóng gói và đóng gói mặc định là 4 byte.

17

Tôi mất của bạn mã, như là, và nói thêm:

#include <libxml/parser.h> 
#include <iostream> 

sau đó đổi tên thành chức năng để main() và biên dịch nó trên x86-64 Fedora 22, trong đó có libxml2 2.9.2

Mã kết quả chạy thành công, sử dụng tệp mẫu, không có segfaults. Thậm chí valgrind không phát hiện thấy vi phạm quyền truy cập bộ nhớ. Như bằng chứng, kết quả, nhật ký strace viết tắt như sau:

stat("Pin.xml", {st_mode=S_IFREG|0644, st_size=362, ...}) = 0 
stat("Pin.xml", {st_mode=S_IFREG|0644, st_size=362, ...}) = 0 
stat("Pin.xml", {st_mode=S_IFREG|0644, st_size=362, ...}) = 0 
open("Pin.xml", O_RDONLY)    = 3 
lseek(3, 0, SEEK_CUR)     = 0 
read(3, "<?xml version=\"1.0\"?>\n\n<servers>\n\n<server_info>\n\n <server_name>Server1</server_name>\n\n <server_ip>127.0.0.1</server_ip> \n\n <server_data_port>9000</server_data_port> \n\n</server_info>\n\n<server_info>\n\n <server_name>Server2</server_name> \n\n <ser"..., 8192) = 362 
read(3, "", 7830)      = 0 
getcwd("/tmp", 1024)     = 5 
close(3)        = 0 
exit_group(0)       = ? 
+++ exited with 0 +++ 

Mặc dù đây là Fedora với libxml2 và gcc hơi mới, sự khác biệt này không quan trọng. Câu trả lời ở đây là không có gì sai với mã được hiển thị ở đây. Tôi thấy không có gì sai với nó. Nhưng nó rõ ràng là một phần của một ứng dụng lớn hơn nhiều, và sự tham nhũng bộ nhớ của bạn đang xảy ra trong một số phần khác của ứng dụng của bạn, và nó chỉ thể hiện khi thực thi ứng dụng của bạn đạt đến phần này.

Điều về C++ là do mã bị treo tại một điểm cụ thể, điều đó không có nghĩa là dòng mã cụ thể này là nơi xảy ra sự cố. Nó không phải là quá khó để đưa ra một ví dụ đơn giản:

#include <iostream> 
#include <cstring> 

int main() 
{ 

    char foo[3]; 

    strcpy(foo, "FoobarbazXXXXXXXXXXXXXXXXXXXXXX"); 

    for (int i=0; i<100; i++) 
     std::cout << i << std::endl; 
    return 0; 
} 

Lỗi ở đây rõ ràng là xảy ra trong dòng strcpy. Nhưng mã sẽ chạy tốt, và in 100 số từ 0 đến 99, và sụp đổ khi main() trả về. Nhưng, rõ ràng, "trở về 0" không phải là nơi mà lỗi được.

Điều này tương tự với những gì đang xảy ra với ứng dụng của bạn. Một số loại tham nhũng bộ nhớ xảy ra tại một số điểm, mà không ảnh hưởng trọng yếu đến việc thực thi mã cho đến khi mã của bạn cố gắng phân tích cú pháp tệp XML của bạn.

Chào mừng bạn đến với C++.

+0

Cảm ơn, Tôi không nghĩ rằng vấn đề có thể đến từ nơi khác. Chỉ cần theo dõi nhanh, Có cách nào để biên dịch lại mã để thay đổi điểm xảy ra vi phạm bộ nhớ không? – user758114

+0

Điều về bộ nhớ bị hỏng là kết quả là không thể đoán trước, và không có quy tắc hoặc hướng dẫn nào để làm theo, bất cứ điều gì. Có, thật sự, không đơn giản, sơn theo số, công thức hoặc quá trình để theo dõi xuống và định vị các lỗi thực sự. Những điều điển hình tôi thử trong các tình huống này là sử dụng một công cụ phân tích tĩnh như valgrind, hoặc tạm thời thay đổi mã logic để bỏ qua các phần lớn của mã thường được thực hiện, để xem liệu tham nhũng bộ nhớ có biến mất hay không. Tất cả đều đi vào trải nghiệm, kiến ​​thức và hiểu cách CPU chạy mã và cách ứng dụng của bạn hoạt động. –

Các vấn đề liên quan