iOS拯啦、內(nèi)存管理

內(nèi)存管理和分配

內(nèi)存分為5個(gè)區(qū)域澡匪,分別指的是----->棧區(qū)/堆區(qū)/BSS段/數(shù)據(jù)段/代碼段

棧:存儲(chǔ)局部變量,當(dāng)其作用域執(zhí)行完畢之后褒链,就會(huì)被系統(tǒng)立即收回

堆:存儲(chǔ)OC對(duì)象唁情,手動(dòng)申請(qǐng)的字節(jié)空間,需要調(diào)用free來(lái)釋放

BSS段:未初始化的全局變量和靜態(tài)變量甫匹,一旦初始化就會(huì)從BSS段中回收掉甸鸟,轉(zhuǎn)存到數(shù)據(jù)段中

數(shù)據(jù)段:存儲(chǔ)已經(jīng)初始化的全局變量和靜態(tài)變量,以及常量數(shù)據(jù)兵迅,直到結(jié)束程序時(shí)才會(huì)被立即收回

代碼段:代碼抢韭,直到結(jié)束程序時(shí)才會(huì)被立即收回

除了堆區(qū),其他區(qū)域的中存儲(chǔ)的數(shù)據(jù)恍箭,都是由系統(tǒng)自動(dòng)釋放的刻恭,堆區(qū)中的OC對(duì)象,是不會(huì)自動(dòng)釋放的扯夭,如果不主動(dòng)釋放鳍贾,那么將在程序結(jié)束的時(shí)候才去釋放

舉例:

當(dāng)?shù)谝粋€(gè)人進(jìn)入辦公室時(shí),他需要使用燈交洗,于是開燈骑科,引用計(jì)數(shù)為1

當(dāng)另一個(gè)人進(jìn)入辦公室時(shí),他也需要燈构拳,引用計(jì)數(shù)為2咆爽;每當(dāng)多一個(gè)人進(jìn)入辦公室時(shí)梁棠,引用計(jì)數(shù)加1

當(dāng)有一個(gè)人離開辦公室時(shí),引用計(jì)數(shù)減1伍掀,當(dāng)引用計(jì)數(shù)為0時(shí)掰茶,也就是最后一個(gè)人離開辦公室時(shí),他不再需要使用燈蜜笤,關(guān)燈離開辦公室濒蒋。

當(dāng)你alloc一個(gè)對(duì)象objc,此時(shí)RC=1把兔;在某個(gè)地方你又retain這個(gè)對(duì)象objc沪伙,此時(shí)RC加1,也就是RC=2县好;由于調(diào)用alloc/retain一次围橡,對(duì)應(yīng)需要調(diào)用release一次來(lái)釋放對(duì)象objc,所以你需要release對(duì)象objc兩次缕贡,此時(shí)RC=0翁授;而當(dāng)RC=0時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用dealloc方法釋放對(duì)象晾咪。


Autorelease Pool ?自動(dòng)釋放池

在釋放池中的調(diào)用了autorelease方法的對(duì)象都會(huì)被壓在該池的頂部(以棧的形式管理對(duì)象)收擦。當(dāng)自動(dòng)釋放池被銷毀的時(shí)候,在該池中的對(duì)象會(huì)自動(dòng)調(diào)用release方法來(lái)釋放資源谍倦,銷毀對(duì)象塞赂。以此來(lái)達(dá)到自動(dòng)管理內(nèi)存的目的。

在開發(fā)中昼蛀,我們常常都會(huì)使用到局部變量宴猾,局部變量一個(gè)特點(diǎn)就是當(dāng)它超過(guò)作用域時(shí),就會(huì)自動(dòng)釋放叼旋。而autorelease pool跟局部變量類似仇哆,當(dāng)執(zhí)行代碼超過(guò)autorelease pool塊時(shí),所有放在autorelease pool的對(duì)象都會(huì)自動(dòng)調(diào)用release夫植。它的工作原理如下:

?RunLoop :?1(等待消息) -> 2(將要處理消息) -> 3(處理消息) -> 4(消息處理完成) -> 1(等待消息)

你也可以將消息(message)這個(gè)詞換成信號(hào)(signal)或者事件(Event)税产。當(dāng)沒(méi)有消息到來(lái)的時(shí)候,這個(gè)線程就會(huì)休眠偷崩,等待消息到來(lái)后觸發(fā)處理過(guò)程。

AutoreleasePool是在什么時(shí)候創(chuàng)建的撞羽,又是在什么時(shí)候被銷毀阐斜?

App啟動(dòng)后,系統(tǒng)在主線程RunLoop 里注冊(cè)兩個(gè)Observser,其回調(diào)都是_wrapRunLoopWithAutoreleasePoolHandler()诀紊。

第一個(gè) Observer 監(jiān)視的事件?

是 Entry(即將進(jìn)入Loop)谒出,其回調(diào)內(nèi)會(huì)調(diào)用 _objc_autoreleasePoolPush() 創(chuàng)建自動(dòng)釋放池。其優(yōu)先級(jí)最高,保證創(chuàng)建釋放池發(fā)生在其他所有回調(diào)之前笤喳。

第二個(gè) Observer 監(jiān)視了兩個(gè)事件

_BeforeWaiting(準(zhǔn)備進(jìn)入休眠) 時(shí)_

調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池为居;

_Exit(即將退出Loop) 時(shí)_

調(diào)用 _objc_autoreleasePoolPop() 來(lái)釋放自動(dòng)釋放池。這個(gè) Observer 優(yōu)先級(jí)最低杀狡,保證其釋放池子發(fā)生在其他所有回調(diào)之后蒙畴。

在主線程執(zhí)行的代碼,通常是寫在諸如事件回調(diào)呜象、Timer回調(diào)內(nèi)的膳凝。這些回調(diào)會(huì)被 RunLoop 創(chuàng)建好的 AutoreleasePool 環(huán)繞著,所以不會(huì)出現(xiàn)內(nèi)存泄漏恭陡,開發(fā)者也不必顯示創(chuàng)建 Pool 了蹬音。

現(xiàn)在我們知道了AutoreleasePool是在RunLoop即將進(jìn)入RunLoop和準(zhǔn)備進(jìn)入休眠這兩種狀態(tài)的時(shí)候被創(chuàng)建和銷毀的。

所以AutoreleasePool的釋放有如下兩種情況休玩。

一是Autorelease對(duì)象是在當(dāng)前的runloop迭代結(jié)束時(shí)釋放的著淆,而它能夠釋放的原因是系統(tǒng)在每個(gè)runloop迭代中都加入了自動(dòng)釋放池Push和Pop。

二是手動(dòng)調(diào)用AutoreleasePool的釋放方法(drain方法)來(lái)銷毀AutoreleasePool


創(chuàng)建一個(gè)NSAutoreleasePool對(duì)象

在autorelease pool塊的對(duì)象調(diào)用autorelease方法

釋放NSAutoreleasePool對(duì)象

NSAutoreleasePool?*pool?=?[[NSAutoreleasePool?alloc]?init];

//?put?object?into?pool

id?obj?= [[[NSObject ?alloc] ?init] ?autorelease];

[pool?drain];

/*?超過(guò)autorelease?pool作用域范圍時(shí)拴疤,obj會(huì)自動(dòng)調(diào)用release方法?*/

由于放在autorelease pool的對(duì)象并不會(huì)馬上釋放永部,如果有大量圖片數(shù)據(jù)放在這里的話遥赚,將會(huì)導(dǎo)致內(nèi)存不足扬舒。(一次runloop結(jié)束后釋放)

for(int?i?=?0;?i?<?numberOfImages;?i++)

{

??????/*???處理圖片,例如加載

???????*???太多autoreleased?objects存在

???????*???由于NSAutoreleasePool對(duì)象沒(méi)有被釋放

???????*???在某個(gè)時(shí)刻,會(huì)導(dǎo)致內(nèi)存不足?

???????*/

}


在ARC內(nèi)存管理機(jī)制中,id和其他對(duì)象類型變量必須是以下四個(gè)ownership qualifiers其中一個(gè)來(lái)修飾:

__strong(默認(rèn)费奸,如果不指定其他,編譯器就默認(rèn)加入)

__weak

__unsafe_unretained

__autoreleasing


__strong ownership qualifier

如果我想創(chuàng)建一個(gè)字符串丛肮,使用完之后將它釋放調(diào)用,使用MRC管理內(nèi)存的寫法應(yīng)該是這樣:

{

????NSString?*text?=?[[NSString?alloc]?initWithFormat:@"Hello,?world"];???//@"Hello,?world"對(duì)象的RC=1

????NSLog(@"%@",?text);

????[text?release];??????????????????????//@"Hello,?world"對(duì)象的RC=0

}

而如果是使用ARC方式的話,就text對(duì)象無(wú)需調(diào)用release方法桩皿,而是當(dāng)text變量超過(guò)作用域時(shí)暖呕,編譯器來(lái)自動(dòng)加入[text release]方法來(lái)釋放內(nèi)存

{

????NSString?*text?=?[[NSString?alloc]?initWithFormat:@"Hello,?world"];????//@"Hello,?world"對(duì)象 RC=1

????NSLog(@"%@",?text);

}

/* ?當(dāng)text超過(guò)作用域時(shí)库物,@"Hello,?world"對(duì)象會(huì)自動(dòng)釋放镀虐,RC=0 ? */

而當(dāng)你將text賦值給其他變量anotherText時(shí)辈毯,MRC需要retain一下來(lái)持有所有權(quán),當(dāng)text和anotherText使用完之后搜贤,各個(gè)調(diào)用release方法來(lái)釋放谆沃。{

????NSString?*text?=?[[NSString?alloc]?initWithFormat:@"Hello,?world"];????//@"Hello,?world"對(duì)象 RC=1

????NSLog(@"%@",?text);

? ? NSString?*anotherText?=?text;????????//@"Hello,?world"對(duì)象的RC=1

????[anotherText?retain];????????????????//@"Hello,?world"對(duì)象的RC=2

????NSLog(@"%@",?anotherText);

? ? [text?release];??????????????????????//@"Hello,?world"對(duì)象的RC=1

????[anotherText?release];???????????????//@"Hello,?world"對(duì)象的RC=0

}

而使用ARC的話,并不需要調(diào)用retain和release方法來(lái)持有跟釋放對(duì)象仪芒。{

????NSString?*text?=?[[NSString?alloc]?initWithFormat:@"Hello,?world"];???//@"Hello,?world"對(duì)象的RC=1

????NSLog(@"%@",?text);


????NSString?*anotherText?=?text;????????//@"Hello,?world"對(duì)象的RC=2

????NSLog(@"%@",?anotherText);

}

/ *??當(dāng)text和anotherText超過(guò)作用域時(shí)唁影,會(huì)自動(dòng)調(diào)用[text?release]和[anotherText?release]方法 ??

@"Hello,?world"對(duì)象的RC=0 ? */

除了當(dāng)__strong變量超過(guò)作用域時(shí),編譯器會(huì)自動(dòng)加入release語(yǔ)句來(lái)釋放內(nèi)存掂名,如果你將__strong變量重新賦給它其他值据沈,那么編譯器也會(huì)自動(dòng)加入release語(yǔ)句來(lái)釋放變量指向之前的對(duì)象。例如:

{

????NSString?*text?=?[[NSString?alloc]?initWithFormat:@"Hello,?world"];????//@"Hello,?world"對(duì)象的RC=1

????NSString?*anotherText?=?text;????????//@"Hello,?world"對(duì)象的RC=2

????NSString?*anotherText?=?[[NSString?alloc]?initWithFormat:@"Sam?Lau"];??//?由于anotherText對(duì)象引用另一個(gè)對(duì)象@"Sam?Lau"饺蔑,那么就會(huì)自動(dòng)調(diào)用[anotherText?release]方法锌介,使得@"Hello,?world"對(duì)象的RC=1,?@"Sam?Lau"對(duì)象的RC=1

}

/*

?*??當(dāng)text和anotherText超過(guò)作用域時(shí),會(huì)自動(dòng)調(diào)用[text?release]和[anotherText?release]方法猾警,

?*??@"Hello,?world"對(duì)象的RC=0和@"Sam?Lau"對(duì)象的RC=0

?*/


我們總結(jié)一下編譯器是按以下方法來(lái)實(shí)現(xiàn)的:

對(duì)于規(guī)則1和規(guī)則2孔祸,是通過(guò)__strong變量來(lái)實(shí)現(xiàn),

對(duì)于規(guī)則3來(lái)說(shuō)肿嘲,當(dāng)變量超過(guò)它的作用域或被賦值或成員變量被丟棄時(shí)就能實(shí)現(xiàn)

對(duì)于規(guī)則4融击,當(dāng)RC=0時(shí),系統(tǒng)就會(huì)自動(dòng)調(diào)用


__weak ownership qualifier

其實(shí)編譯器根據(jù)__strong修飾符來(lái)管理對(duì)象內(nèi)存雳窟。但是__strong并不能解決引用循環(huán)(Reference Cycle)問(wèn)題:對(duì)象A持有對(duì)象B尊浪,反過(guò)來(lái),對(duì)象B持有對(duì)象A封救;這樣會(huì)導(dǎo)內(nèi)存造成內(nèi)存泄露問(wèn)題拇涤。



@interface?Test?:?NSObject

@property?(strong,?nonatomic)?id?objc;

@end

{

????Test?*test1?=?[Test?new];????????/*?對(duì)象a?*/

????/*?test1有一個(gè)強(qiáng)引用到對(duì)象a?*/


????Test?*test2?=?[Test?new];????????/*?對(duì)象b?*/

????/*?test2有一個(gè)強(qiáng)引用到對(duì)象b?*/


????test1.objc?=?test2;??????????????/*?對(duì)象a的成員變量objc有一個(gè)強(qiáng)引用到對(duì)象b?*/

????test2.objc?=?test1;??????????????/*?對(duì)象b的成員變量objc有一個(gè)強(qiáng)引用到對(duì)象a?*/

}

/*???當(dāng)變量test1超過(guò)它作用域時(shí),它指向a對(duì)象會(huì)自動(dòng)release

?*???當(dāng)變量test2超過(guò)它作用域時(shí)誉结,它指向b對(duì)象會(huì)自動(dòng)release

?*???此時(shí)鹅士,b對(duì)象的objc成員變量仍持有一個(gè)強(qiáng)引用到對(duì)象a

?*???此時(shí),a對(duì)象的objc成員變量仍持有一個(gè)強(qiáng)引用到對(duì)象b

?*???于是發(fā)生內(nèi)存泄露

?*/

如何解決惩坑?于是我們引用一個(gè)__weakownership qualifier掉盅,被它修飾的變量都不持有對(duì)象的所有權(quán)也拜,而且當(dāng)變量指向的對(duì)象的RC為0時(shí),變量設(shè)置為nil趾痘。例如:

__weak?NSString?*text?=?[[NSString?alloc]?initWithFormat:@"Sam?Lau"];

NSLog(@"%@",?text);

由于text變量被__weak修飾慢哈,text并不持有@"Sam Lau"對(duì)象的所有權(quán),@"Sam Lau"對(duì)象一創(chuàng)建就馬上被釋放永票,并且編譯器給出警告卵贱,所以打印結(jié)果為(null)。

所以侣集,針對(duì)剛才的引用循環(huán)問(wèn)題键俱,只需要將Test類的屬性objc設(shè)置weak修飾符,那么就能解決世分。

@property?(weak,?nonatomic)?id?objc;


__unsafe_unretained ownership qualifier

__unsafe_unretained ownership qualifier编振,正如名字所示,它是不安全的罚攀。它跟__weak相似党觅,被它修飾的變量都不持有對(duì)象的所有權(quán),但當(dāng)變量指向的對(duì)象的RC為0時(shí)斋泄,變量并不設(shè)置為nil杯瞻,而是繼續(xù)保存對(duì)象的地址;這樣的話炫掐,對(duì)象有可能已經(jīng)釋放魁莉,但繼續(xù)訪問(wèn),就會(huì)造成非法訪問(wèn)(Invalid Access)募胃。例子如下:

__unsafe_unretained?id?obj0?=?nil;

{

????id?obj1?=?[[NSObject?alloc]?init];?????//?對(duì)象A

????/*?由于obj1是強(qiáng)引用旗唁,所以obj1持有對(duì)象A的所有權(quán),對(duì)象A的RC=1?*/

????obj0?=?obj1;

????/*?由于obj0是__unsafe_unretained痹束,它不持有對(duì)象A的所有權(quán)检疫,但能夠引用它,對(duì)象A的RC=1?*/

????NSLog(@"A:?%@",?obj0);

}

/*?當(dāng)obj1超過(guò)它的作用域時(shí)祷嘶,它指向的對(duì)象A將會(huì)自動(dòng)釋放?*/

NSLog(@"B:?%@",?obj0);

/*?由于obj0是__unsafe_unretained屎媳,當(dāng)它指向的對(duì)象RC=0時(shí),它會(huì)繼續(xù)保存對(duì)象的地址论巍,所以兩個(gè)地址相同?*/


如果將__unsafe_unretained改為weak的話烛谊,兩個(gè)打印結(jié)果將不同

__weak?id?obj0?=?nil;

{

????id?obj1?=?[[NSObject?alloc]?init];?????//?對(duì)象A

????/*?由于obj1是強(qiáng)引用,所以obj1持有對(duì)象A的所有權(quán)嘉汰,對(duì)象A的RC=1?*/

????obj0?=?obj1;

????/*?由于obj0是__unsafe_unretained丹禀,它不持有對(duì)象A的所有權(quán),但能夠引用它,對(duì)象A的RC=1?*/

????NSLog(@"A:?%@",?obj0);

}

/*?當(dāng)obj1超過(guò)它的作用域時(shí)双泪,它指向的對(duì)象A將會(huì)自動(dòng)釋放?*/

NSLog(@"B:?%@",?obj0);

/*?由于obj0是__weak持搜,?當(dāng)它指向的對(duì)象RC=0時(shí),它會(huì)自動(dòng)設(shè)置為nil焙矛,所以兩個(gè)打印結(jié)果將不同*/


__autoreleasing ownership qualifier

引入ARC之后朵诫,讓我們看看autorelease pool有哪些變化。沒(méi)有ARC之前的寫法如下:

NSAutoreleasePool?*pool?=?[[NSAutoreleasePool?alloc]?init];

//?put?object?into?pool

id?obj?=?[[NSObject?alloc]?init];

[obj?autorelease];

[pool?drain];

/*?超過(guò)autorelease?pool作用域范圍時(shí)薄扁,obj會(huì)自動(dòng)調(diào)用release方法?*/

引入ARC之后,寫法比之前更加簡(jiǎn)潔:

@autoreleasepool?{

????id?__autoreleasing?obj?=?[[NSObject?alloc]?init];

}相比之前的創(chuàng)建废累、使用和釋放NSAutoreleasePool對(duì)象邓梅,現(xiàn)在你只需要將代碼放在@autoreleasepool塊即可。你也不需要調(diào)用autorelease方法了邑滨,只需要用__autoreleasing修飾變量即可日缨。


有了ARC之后,新的property modifier也被引入到Objective-C類的property掖看,例如:

@property?(strong,?nonatomic)?NSString?*text;

下面有張表來(lái)展示property modifier與ownership qualifier的對(duì)應(yīng)關(guān)系

iOS 內(nèi)存泄漏監(jiān)測(cè)自動(dòng)化:http://www.cocoachina.com/ios/20170102/18490.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匣距,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子哎壳,更是在濱河造成了極大的恐慌毅待,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件归榕,死亡現(xiàn)場(chǎng)離奇詭異尸红,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)刹泄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門外里,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人特石,你說(shuō)我怎么就攤上這事盅蝗。” “怎么了姆蘸?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵墩莫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我乞旦,道長(zhǎng)贼穆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任兰粉,我火速辦了婚禮故痊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玖姑。我一直安慰自己愕秫,他們只是感情好慨菱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著戴甩,像睡著了一般符喝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甜孤,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天协饲,我揣著相機(jī)與錄音,去河邊找鬼缴川。 笑死茉稠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的把夸。 我是一名探鬼主播而线,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼恋日!你這毒婦竟也來(lái)了膀篮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤岂膳,失蹤者是張志新(化名)和其女友劉穎誓竿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闷营,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烤黍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傻盟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片速蕊。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖娘赴,靈堂內(nèi)的尸體忽然破棺而出规哲,到底是詐尸還是另有隱情,我是刑警寧澤诽表,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布唉锌,位于F島的核電站,受9級(jí)特大地震影響竿奏,放射性物質(zhì)發(fā)生泄漏袄简。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一泛啸、第九天 我趴在偏房一處隱蔽的房頂上張望绿语。 院中可真熱鬧,春花似錦、人聲如沸吕粹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)匹耕。三九已至聚请,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稳其,已是汗流浹背驶赏。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留既鞠,地道東北人母市。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像损趋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子椅寺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容