2010-08-21 155 views
3

我有一個奇怪的問題。我在我的應用程序中使用Apple私有框架中的方法。當我第一次打電話時,它就可以工作。當我第二次立即調用它時,它們之間沒有任何東西,它會崩潰。但是,如果我將NSLog放在兩個調用之間,那麼它的功能非常好。所以我嘗試刪除NSLog,並在它們之間放置for-loops,sleep(),printf(「...」)和fprintf(stderr,「...」)來模擬NSLog,但它沒有幫助。我想知道該方法如何知道我使用NSLog?換句話說,NSLog實際上做了什麼來影響該方法的行爲?NSLog實際上做了什麼?

非常感謝!

編輯:

我似乎解決了這個問題。我會在這裏分享我的解決方案,並希望對某些人有用。

我正在使用MultitouchSupport.framework創建一個多點觸控相關的應用程序。我複製了http://aladino.dmi.unict.it/?a=multitouch中的代碼,並在循環結尾添加了CFRelease。所以,基本上,我的主要方法是這樣的:

int main(void) { 
    int i; 
    NSMutableArray* deviceList = (NSMutableArray*)MTDeviceCreateList(); //grab our device list 
    for(i = 0; i<[deviceList count]; i++) { //iterate available devices 
     MTRegisterContactFrameCallback([deviceList objectAtIndex:i], touchCallback); //assign callback for device 
     MTDeviceStart([deviceList objectAtIndex:i], 0); //start sending events 
    } 
    CFRelease((CFMutableArrayRef)deviceList); 
    printf("Ctrl-C to abort\n"); 
    sleep(-1); 
    return 0; 
} 

運行一段時間後,它會顯示「程序接收到的信號:‘EXC_BAD_ACCESS’。」 這裏是堆棧跟蹤:

#0 0x7fff8795496e in ParsedMultitouchFrameRepInitialize 
#1 0x7fff879565b1 in mt_HandleMultitouchFrame 
#2 0x7fff87955a03 in mt_DequeueDataFromDriver 
#3 0x7fff87955b29 in mt_DequeueMultitouchDataFromDriverThreadEntry 
#4 0x7fff831b3456 in _pthread_start 
#5 0x7fff831b3309 in thread_start 

但是,如果我把下面的NSLog MTDeviceStart,它不會崩潰。

我將CFRelease((CFMutableArrayRef)deviceList)添加到原始代碼的原因是我認爲從名爲* Create *或* Copy *的函數創建的對象應該由我們自己釋放。但事實證明,如果我像原始代碼一樣刪除它,即使沒有使用NSLog,它也不會崩潰。

所以,也許是因爲我發佈deviceList太早?但是如果是這樣,爲什麼NSLog似乎能夠防止崩潰?

+5

它可能與NSLog無關。我會發布一些代碼。 – 2010-08-21 04:01:32

+0

請編輯代碼和堆棧跟蹤到您的問題。 – 2010-08-21 05:35:22

+0

你對命名約定是正確的,但由於'MTDeviceCreateList'是一個私有函數,它可能違反/不符合它。 (也許這意味着「創建設備數組,以便在進程期間保持活動狀態,並將指針返回給它」)。嘗試在樂器的殭屍工具下運行程序(崩潰)。因此,您應該能夠證明您的版本是否過度釋放,或者以其他方式確定崩潰的真正原因。 – 2010-08-21 12:12:53

回答

0

這可能是一個內存管理問題:可能是無關的釋放。如果您發佈回溯,這可能會有助於追蹤問題。 (事實證明,昨天晚上我在Twitter上有人提到了這樣的事情)。

+0

哇!非常感謝你。我嘗試從我的代碼中刪除一個CFRelease,現在它完美地工作。我不知道爲什麼。我剛剛將我的代碼添加到了我的問題中。 – ifvc 2010-08-21 07:15:05

+0

小心:如果它被釋放得太早,但仍然需要最終被釋放,這意味着它現在不會崩潰,而是會發生泄漏(例如,如果它是時間問題,並且您保留的計數是正確的開始) – 2012-07-27 20:57:32

1

需要很長時間。我不知道爲什麼。它會打印日期/時間,進程名稱,進程ID,線程ID和(最後)要求的字符串。我想認爲它也發送日誌消息到syslogd(無論是Xcode或iPCU的控制檯顯示多行NSLogs作爲一個單一的項目,我忘記了); IPC可能有重大意義。

使用syslog()(#import <syslog.h>然後syslog(LOG_INFO, "Hello there!");,如果它的工作原理,但你沒有輸出,嘗試改變優先級(參見man 3 syslog)嘗試

+0

是的,NSLog將消息發送到ASL,與syslog一樣。我不確定你希望系統日誌有什麼不同 - 只是不打印到stderr? – 2010-08-21 05:34:26

+0

我在迴應「如果我把兩個調用之間的NSLog,它的工作原理」,這表明syslog()可能會做一些事情,NSLog使它「工作」。 – 2010-08-23 01:54:21

2

事情與此類似:

static inline void NSLogMessageString(NSString *string){ 
    NSString *date=[[NSDate date] 
    descriptionWithCalendarFormat:@"%Y-%m-%d %H:%M:%S.%F" 
         timeZone:nil locale:nil]; 
    NSString *process=[[NSProcessInfo processInfo] processName]; 

    NSLogFormat(@"%@ %@[%d:%lx] %@",date,process,NSPlatformProcessID(),NSPlatformThreadID(),string); 
} 

void NSLogv(NSString *format,va_list arguments) { 
    NSString *string=NSStringNewWithFormat(format,nil,arguments,NULL); 

    NSLogMessageString(string); 

[string release]; 
} 

void NSLog(NSString *format,...) { 
    va_list arguments; 

    va_start(arguments,format); 

    NSLogv(format,arguments); 
} 

謝謝對於問這個問題大聲笑,我想重寫它,所以我可以添加調試變量,這意味着我可以在需要時關閉所有NSLogging調用..

+0

- 在NSObjcRuntime中找到 – 2010-08-21 08:05:05

1

NSLog可以影響像你正在運行的int因爲它影響線程執行的順序,因爲當你在後臺線程中調用NSLog時,它必須獲得對stdout的獨佔訪問權限。printf調試棘手的線程問題常常導致「heisenbugs」出於這個原因(即當你試圖檢查它們時它們會改變行爲)。

相關問題